diff --git a/DEPS b/DEPS index 52ebc13..f0bd544 100644 --- a/DEPS +++ b/DEPS
@@ -245,19 +245,19 @@ # 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': '87aa7a909514282fdb865b2674cf82acf300995d', + 'skia_revision': '507b6dd516b53e5045c3fa1108218bd1a89b6641', # 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': '5f0fffcf877b801c2ab2d0b3057abe7df056cd60', + 'v8_revision': 'bd0b60ae30b2e6e9b21796e541c238bea7735e8c', # 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': 'c48e35b94aa3ed30a6e332c449b48a6958b164e9', + 'angle_revision': '2df2a9ec286dbe26cb68a83d1f0424d07e5fc45c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'c9e8f23b0fb8c630cb951964073b2f4498e6b556', + 'swiftshader_revision': 'e576ca6011cdabd89dd8cc64566cc8d8bc2aa99a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -276,7 +276,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling googletest # and whatever else without interference from each other. - 'googletest_revision': '14aa11db02d9851d957f93ef9fddb110c1aafdc6', + 'googletest_revision': '43efa0a4efd40c78b9210d15373112081899a97c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling lighttpd # and whatever else without interference from each other. @@ -312,7 +312,7 @@ # 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': 'b4974c8f859b9ca0e5c7fa03588cb9011563d522', + 'catapult_revision': '25f38be662aec0c8b1509024001e5cc5254a363c', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -320,7 +320,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling devtools-frontend # and whatever else without interference from each other. - 'devtools_frontend_revision': '6ee03fa8edcfd781634036d7a890e015cbbc72dc', + 'devtools_frontend_revision': 'ce54fe62b782f9f90ae586c0a68fa3ecfdc0e255', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libprotobuf-mutator # and whatever else without interference from each other. @@ -360,11 +360,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': 'a064f7c95ca7a023ac9fb802cfbd5ecd7c6014f0', + 'dawn_revision': 'f994c5637c2d03546f2444fd4a0a5b0d6121548f', # 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': '935f2c21ecea07b03c1e4798ef8022da5bd5a344', + 'quiche_revision': 'cfb0cce5c3c0be76e9baf5950a6fff393ba0c158', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling ios_webkit # and whatever else without interference from each other. @@ -388,7 +388,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling nearby # and whatever else without interference from each other. - 'nearby_revision': '9d4ad8a1d72631640d5e4d0161e7fcf6b1d4f21d', + 'nearby_revision': '42059a624b67ebb8d852248c49d0e121f9ad5d35', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling securemessage # and whatever else without interference from each other. @@ -408,7 +408,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. - 'libunwind_revision': 'f2ef96ecb8ecba64489f0412d345698ffb38e094', + 'libunwind_revision': 'b86911d6e7455c4be2ddbc390803aecad19cfc3a', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -663,7 +663,7 @@ Var('chromium_git') + '/external/github.com/toji/webvr.info.git' + '@' + 'c58ae99b9ff9e2aa4c524633519570bf33536248', 'src/docs/website': { - 'url': Var('chromium_git') + '/website.git' + '@' + '8f53a2e1eef4e0bad76e2877982ad3e19b57a211', + 'url': Var('chromium_git') + '/website.git' + '@' + '2b8503489c51fc24cccfab52709087817d274c4c', }, 'src/ios/third_party/earl_grey2/src': { @@ -851,7 +851,7 @@ 'packages': [ { 'package': 'chromium/third_party/androidx', - 'version': 'fCKbgI-2wQuESFG6GNHGXoV1r_7MfjrsOaRv8F7xWa4C', + 'version': 'EqXyh_ypMvWmNBJPk_Xk9bp-pc8lerSz48cySEsnbMwC', }, ], 'condition': 'checkout_android', @@ -1090,7 +1090,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '2721cc95dacb8fbd8e4a6dee9874a803dac82f8f', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '1b93e14c92416185694f8764be425f82fa0d4242', 'src/third_party/devtools-frontend/src': Var('chromium_git') + '/devtools/devtools-frontend' + '@' + Var('devtools_frontend_revision'), @@ -1634,7 +1634,7 @@ }, 'src/third_party/tflite/src': - Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + 'd570144d42b17065ea1c222e9ea38fa1810bee21', + Var('chromium_git') + '/external/github.com/tensorflow/tensorflow.git' + '@' + 'd9e5d3c634c2ab1221e7d30b562c48b0b0e110b7', 'src/third_party/turbine': { 'packages': [ @@ -1694,7 +1694,7 @@ Var('chromium_git') + '/external/github.com/gpuweb/cts.git' + '@' + '729be85c2f01876a1ea075c523d542ebaaa76301', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + 'e79f85c10e98f3a43570d8017321842aaf4165bf', + Var('webrtc_git') + '/src.git' + '@' + 'e0bc8d2f49a6a39958cc33545713c2c6d6035675', 'src/third_party/libgifcodec': Var('skia_git') + '/libgifcodec' + '@'+ Var('libgifcodec_revision'), @@ -1764,7 +1764,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@830ca72184cb069ed4ffd9eed0130609c8629ca1', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@f1fdc8bb591918fb8fe8ba54f2acd85dff570fa7', 'condition': 'checkout_src_internal', }, @@ -1805,7 +1805,7 @@ 'packages': [ { 'package': 'chromeos_internal/apps/media_app/app', - 'version': 'Tav_AojO1FUuEVe0sykGdSBfmtp2L1exqF9u1Ls_XQoC', + 'version': 'jikeZvcWMx8pOe7_zhb-a2CDK9TDceSKzXXghIYMR04C', }, ], 'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/android_webview/browser/gfx/overlay_processor_webview.cc b/android_webview/browser/gfx/overlay_processor_webview.cc index f23ea309a..06fdfe6 100644 --- a/android_webview/browser/gfx/overlay_processor_webview.cc +++ b/android_webview/browser/gfx/overlay_processor_webview.cc
@@ -62,10 +62,16 @@ : return_resource(std::move(return_resource)) { representation_ = shared_image_manager->ProduceOverlay(mailbox, memory_tracker); - if (!representation_) + if (!representation_) { return; + } read_access_ = representation_->BeginScopedReadAccess(false); + if (!read_access_) { + LOG(ERROR) << "Couldn't access shared image for read."; + return; + } + std::vector<gfx::GpuFence> acquire_fences = read_access_->TakeAcquireFences(); if (!acquire_fences.empty()) { @@ -110,6 +116,15 @@ base::ScopedFD TakeBeginReadFence() { return std::move(begin_read_fence_); } AHardwareBuffer* GetAHardwareBuffer() { + // Note, that it's possible that BeginScopedReadAccess() will fail if + // media couldn't get us a frame. We don't fail creation of resource in + // this case, because if affects Surface acks and we don't to change the + // frame submission flow. Instead we just set empty buffer to the surface. + // Note, that it should only happen for the first frame in very rare + // cases. + if (!read_access_) + return nullptr; + DCHECK(representation_); DCHECK(read_access_); @@ -535,8 +550,8 @@ TRACE_EVENT1("gpu,benchmark,android_webview", "OverlayProcessorWebview::Manager::UpdateBufferInTransaction", "has_resource", !!resource); - if (resource) { - auto* buffer = resource->GetAHardwareBuffer(); + auto* buffer = resource ? resource->GetAHardwareBuffer() : nullptr; + if (buffer) { auto crop_rect = resource->crop_rect(); // Crop rect defines the valid portion of the buffer, so we use its as a
diff --git a/android_webview/renderer/aw_content_renderer_client.cc b/android_webview/renderer/aw_content_renderer_client.cc index 5f95fd8..38677b7 100644 --- a/android_webview/renderer/aw_content_renderer_client.cc +++ b/android_webview/renderer/aw_content_renderer_client.cc
@@ -200,9 +200,11 @@ communication->RunScriptsAtDocumentStart(); } -void AwContentRendererClient::AddSupportedKeySystems( - std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) { - AwAddKeySystems(key_systems); +void AwContentRendererClient::GetSupportedKeySystems( + media::GetSupportedKeySystemsCB cb) { + media::KeySystemPropertiesVector key_systems; + AwAddKeySystems(&key_systems); + std::move(cb).Run(std::move(key_systems)); } std::unique_ptr<blink::WebSocketHandshakeThrottleProvider>
diff --git a/android_webview/renderer/aw_content_renderer_client.h b/android_webview/renderer/aw_content_renderer_client.h index c4c58b4..e6eda10 100644 --- a/android_webview/renderer/aw_content_renderer_client.h +++ b/android_webview/renderer/aw_content_renderer_client.h
@@ -52,9 +52,7 @@ uint64_t VisitedLinkHash(const char* canonical_url, size_t length) override; bool IsLinkVisited(uint64_t link_hash) override; void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override; - void AddSupportedKeySystems( - std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) - override; + void GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb) override; std::unique_ptr<blink::WebSocketHandshakeThrottleProvider> CreateWebSocketHandshakeThrottleProvider() override; bool HandleNavigation(content::RenderFrame* render_frame,
diff --git a/ash/BUILD.gn b/ash/BUILD.gn index a2c11d1..fcdaec1 100644 --- a/ash/BUILD.gn +++ b/ash/BUILD.gn
@@ -1627,6 +1627,8 @@ "tray_action/tray_action.cc", "tray_action/tray_action.h", "tray_action/tray_action_observer.h", + "utility/cropping_util.cc", + "utility/cropping_util.h", "utility/haptics_util.cc", "utility/haptics_util.h", "utility/layer_copy_animator.cc", @@ -2655,6 +2657,7 @@ "tray_action/test_tray_action_client.cc", "tray_action/test_tray_action_client.h", "tray_action/tray_action_unittest.cc", + "utility/cropping_util_unittest.cc", "utility/haptics_util_unittest.cc", "utility/layer_copy_animator_unittest.cc", "utility/layer_util_unittest.cc",
diff --git a/ash/ambient/model/ambient_animation_photo_provider.cc b/ash/ambient/model/ambient_animation_photo_provider.cc index af8c06c..a1f64f74 100644 --- a/ash/ambient/model/ambient_animation_photo_provider.cc +++ b/ash/ambient/model/ambient_animation_photo_provider.cc
@@ -4,8 +4,10 @@ #include "ash/ambient/model/ambient_animation_photo_provider.h" +#include <functional> #include <string> #include <utility> +#include <vector> #include "ash/ambient/model/ambient_backend_model.h" #include "ash/ambient/resources/ambient_animation_static_resources.h" @@ -18,6 +20,8 @@ #include "base/rand_util.h" #include "cc/paint/paint_flags.h" #include "cc/paint/skottie_frame_data.h" +#include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/gfx/geometry/size.h" #include "ui/gfx/image/image_skia.h" #include "ui/gfx/image/image_skia_rep.h" @@ -76,6 +80,111 @@ float current_frame_data_scale_factor_ = 0; }; +// Provides images for dynamic assets based on the following UX requirements: +// * Make a best effort to assign portrait images to portrait assets and same +// for landscape. +// * If there are less topics available than the number of dynamic assets in +// the animation, the available photos should be evenly distributed and +// duplicated among the assets. For example, if there are 2 topics available +// and 6 dynamic assets, each topic should appear 3 times. +// * The photos should be shuffled among the assets between animation cycles. +class DynamicImageProvider { + public: + explicit DynamicImageProvider( + const base::circular_deque<PhotoWithDetails>& all_available_topics) { + DCHECK(!all_available_topics.empty()) + << "Animation should not have started rendering without any decoded " + "photos in the model."; + TopicReferenceVector all_available_topics_shuffled = + ShuffleTopics(all_available_topics); + for (auto& topic_ref : all_available_topics_shuffled) { + // Note the AmbientPhotoConfig for animations states that topics from IMAX + // containing primary and related photos should be split into 2. So the + // related photo should always be null (hence no point in reading it). + DCHECK(!topic_ref.get().photo.isNull()); + if (IsPortrait(topic_ref.get().photo.size())) { + portrait_set_.topics.push_back(std::move(topic_ref)); + } else { + landscape_set_.topics.push_back(std::move(topic_ref)); + } + } + } + + gfx::ImageSkia GetImageForAssetSize( + const absl::optional<gfx::Size>& asset_size) { + gfx::ImageSkia image; + // If the |asset_size| is unavailable, this is unexpected but not fatal. The + // choice to default to portrait is arbitrary. + if (!asset_size || IsPortrait(*asset_size)) { + image = GetNextImage(/*primary_topic_set=*/portrait_set_, + /*secondary_topic_set=*/landscape_set_); + } else { + image = GetNextImage(/*primary_topic_set=*/landscape_set_, + /*secondary_topic_set=*/portrait_set_); + } + DCHECK(!image.isNull()); + TryResetCurrentTopicIndices(); + return image; + } + + private: + using TopicReferenceVector = + std::vector<std::reference_wrapper<const PhotoWithDetails>>; + + struct TopicSet { + // Not mutated after DynamicImageProvider's constructor. + TopicReferenceVector topics; + // Incremented each time a topic is picked from the set and loops back to + // 0 when all topics from all TopicSets have been exhausted. + size_t current_topic_idx = 0; + }; + + static TopicReferenceVector ShuffleTopics( + const base::circular_deque<PhotoWithDetails>& all_available_topics) { + TopicReferenceVector topics_shuffled; + for (const PhotoWithDetails& topic : all_available_topics) { + topics_shuffled.push_back(std::cref(topic)); + } + base::RandomShuffle(topics_shuffled.begin(), topics_shuffled.end()); + return topics_shuffled; + } + + static bool IsPortrait(const gfx::Size& size) { + DCHECK(!size.IsEmpty()); + return size.height() > size.width(); + } + + static gfx::ImageSkia GetNextImageFromTopicSet(TopicSet& topic_set) { + if (topic_set.current_topic_idx >= topic_set.topics.size()) + return gfx::ImageSkia(); + + gfx::ImageSkia image = + topic_set.topics[topic_set.current_topic_idx].get().photo; + ++topic_set.current_topic_idx; + return image; + } + + static gfx::ImageSkia GetNextImage(TopicSet& primary_topic_set, + TopicSet& secondary_topic_set) { + gfx::ImageSkia image = GetNextImageFromTopicSet(primary_topic_set); + return image.isNull() ? GetNextImageFromTopicSet(secondary_topic_set) + : image; + } + + void TryResetCurrentTopicIndices() { + // Once all available topics have been exhausted, reset the + // |current_topic_idx| for each TopicSet to start "fresh" again. + if (landscape_set_.current_topic_idx >= landscape_set_.topics.size() && + portrait_set_.current_topic_idx >= portrait_set_.topics.size()) { + landscape_set_.current_topic_idx = 0; + portrait_set_.current_topic_idx = 0; + } + } + + TopicSet landscape_set_; + TopicSet portrait_set_; +}; + } // namespace class AmbientAnimationPhotoProvider::DynamicImageAssetImpl @@ -90,9 +199,14 @@ // the refresh callback will be run exactly once regardless of the number of // frames in a cycle or dynamic assets in the animation. DynamicImageAssetImpl(base::StringPiece asset_id, + absl::optional<gfx::Size> size, base::RepeatingClosure refresh_image_cb) - : asset_id_(asset_id), refresh_image_cb_(std::move(refresh_image_cb)) { + : asset_id_(asset_id), + size_(std::move(size)), + refresh_image_cb_(std::move(refresh_image_cb)) { DCHECK(refresh_image_cb_); + if (!size_) + DLOG(ERROR) << "Dimensions unavailable for dynamic asset " << asset_id_; } void AssignNewImage(gfx::ImageSkia image) { @@ -126,6 +240,8 @@ return current_frame_data_; } + const absl::optional<gfx::Size>& size() const { return size_; } + private: static constexpr float kAnimationTimestampInvalid = -1.f; @@ -143,6 +259,7 @@ } const std::string asset_id_; + const absl::optional<gfx::Size> size_; const base::RepeatingClosure refresh_image_cb_; // Last animation frame timestamp that was observed. float last_observed_animation_timestamp_ = kAnimationTimestampInvalid; @@ -173,7 +290,7 @@ // change once the animation starts rendering. if (ambient::util::IsDynamicLottieAsset(asset_id)) { dynamic_assets_.push_back(base::MakeRefCounted<DynamicImageAssetImpl>( - asset_id, + asset_id, size, base::BindRepeating( &AmbientAnimationPhotoProvider::RefreshDynamicImageAssets, // In practice, this could be Unretained since the provider will @@ -187,6 +304,9 @@ weak_factory_.GetWeakPtr()))); return dynamic_assets_.back(); } else { + // For static assets, the |size| isn't needed. It should match the size of + // the image loaded from animation's |static_resources_| since that is the + // very image created by UX when the animation was built. return base::MakeRefCounted<StaticImageAssetImpl>(asset_id, *static_resources_); } @@ -194,31 +314,10 @@ void AmbientAnimationPhotoProvider::RefreshDynamicImageAssets() { DVLOG(4) << __func__; - const base::circular_deque<PhotoWithDetails>& all_available_topics = - backend_model_->all_decoded_topics(); - DCHECK(!all_available_topics.empty()) - << "Animation should not have started rendering without any decoded " - "photos in the model."; - // UX requirements: - // 1) If there are less topics available than the number of dynamic assets in - // the animation, the available photos should be evenly distributed and - // duplicated among the assets. For example, if there are 2 topics - // available and 6 dynamic assets, each topic should appear 3 times. - // 2) The photos should be shuffled among the assets between animation cycles. - std::vector<gfx::ImageSkia> assigned_images(dynamic_assets_.size()); - size_t decoded_topic_idx = 0; - for (gfx::ImageSkia& image_to_assign : assigned_images) { - DCHECK(!all_available_topics[decoded_topic_idx].photo.isNull()); - // Note the AmbientPhotoConfig for animations states that topics from IMAX - // containing primary and related photos should be split into 2. So the - // related photo should always be null (hence no point in reading it here). - image_to_assign = all_available_topics[decoded_topic_idx].photo; - decoded_topic_idx = (decoded_topic_idx + 1) % all_available_topics.size(); - } - - base::RandomShuffle(assigned_images.begin(), assigned_images.end()); - for (size_t asset_idx = 0; asset_idx < dynamic_assets_.size(); ++asset_idx) { - dynamic_assets_[asset_idx]->AssignNewImage(assigned_images[asset_idx]); + DynamicImageProvider image_provider(backend_model_->all_decoded_topics()); + for (const auto& dynamic_asset : dynamic_assets_) { + dynamic_asset->AssignNewImage( + image_provider.GetImageForAssetSize(dynamic_asset->size())); } }
diff --git a/ash/ambient/model/ambient_animation_photo_provider_unittest.cc b/ash/ambient/model/ambient_animation_photo_provider_unittest.cc index e19dd3e..408a439e 100644 --- a/ash/ambient/model/ambient_animation_photo_provider_unittest.cc +++ b/ash/ambient/model/ambient_animation_photo_provider_unittest.cc
@@ -20,6 +20,7 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/gfx/geometry/size.h" #include "ui/gfx/image/image_unittest_util.h" namespace ash { @@ -69,19 +70,23 @@ model_.AddNextImage(decoded_topic); } - scoped_refptr<ImageAsset> LoadAsset(base::StringPiece asset_id) { + scoped_refptr<ImageAsset> LoadAsset( + base::StringPiece asset_id, + absl::optional<gfx::Size> size = absl::nullopt) { scoped_refptr<ImageAsset> asset = provider_.LoadImageAsset( asset_id, base::FilePath("dummy-resource-path/dummy-resource-name"), - /*size=*/absl::nullopt); + std::move(size)); CHECK(asset) << asset_id; return asset; } - std::vector<scoped_refptr<ImageAsset>> LoadAllDynamicAssets() { + std::vector<scoped_refptr<ImageAsset>> LoadAllDynamicAssets( + std::array<absl::optional<gfx::Size>, kNumDynamicAssets> asset_sizes = + std::array<absl::optional<gfx::Size>, kNumDynamicAssets>()) { std::vector<scoped_refptr<ImageAsset>> all_assets; for (int asset_idx = 0; asset_idx < kNumDynamicAssets; ++asset_idx) { - all_assets.push_back( - LoadAsset(GenerateTestLottieDynamicAssetId(asset_idx))); + all_assets.push_back(LoadAsset( + GenerateTestLottieDynamicAssetId(asset_idx), asset_sizes[asset_idx])); } return all_assets; } @@ -241,4 +246,85 @@ HasImageDimensions(11, 11))); } +TEST_F(AmbientAnimationPhotoProviderTest, MatchesDynamicAssetOrientation) { + // 2 landscape 2 portrait + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/10, /*height=*/20)); + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/20, /*height=*/10)); + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/20, /*height=*/40)); + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/40, /*height=*/20)); + + std::vector<scoped_refptr<ImageAsset>> all_assets = + LoadAllDynamicAssets({gfx::Size(100, 50), gfx::Size(50, 100), + gfx::Size(100, 50), gfx::Size(50, 100)}); + + std::vector<cc::SkottieFrameData> frame_data = + GetFrameDataForAssets(all_assets, /*timestamp=*/0); + EXPECT_THAT(std::vector<cc::SkottieFrameData>({frame_data[0], frame_data[2]}), + UnorderedElementsAre(HasImageDimensions(20, 10), + HasImageDimensions(40, 20))); + EXPECT_THAT(std::vector<cc::SkottieFrameData>({frame_data[1], frame_data[3]}), + UnorderedElementsAre(HasImageDimensions(10, 20), + HasImageDimensions(20, 40))); + GetFrameDataForAssets(all_assets, /*timestamp=*/1); + + // 3 landscape 1 portrait + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/10, /*height=*/20)); + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/20, /*height=*/10)); + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/30, /*height=*/20)); + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/40, /*height=*/30)); + frame_data = GetFrameDataForAssets(all_assets, /*timestamp=*/0); + EXPECT_THAT(frame_data[1], HasImageDimensions(10, 20)); + EXPECT_THAT(std::vector<cc::SkottieFrameData>( + {frame_data[0], frame_data[2], frame_data[3]}), + UnorderedElementsAre(HasImageDimensions(20, 10), + HasImageDimensions(30, 20), + HasImageDimensions(40, 30))); + GetFrameDataForAssets(all_assets, /*timestamp=*/1); + + // 1 landscape 3 portrait + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/10, /*height=*/20)); + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/20, /*height=*/10)); + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/20, /*height=*/40)); + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/30, /*height=*/50)); + frame_data = GetFrameDataForAssets(all_assets, /*timestamp=*/0); + EXPECT_THAT(frame_data[0], HasImageDimensions(20, 10)); + EXPECT_THAT(std::vector<cc::SkottieFrameData>( + {frame_data[1], frame_data[2], frame_data[3]}), + UnorderedElementsAre(HasImageDimensions(10, 20), + HasImageDimensions(20, 40), + HasImageDimensions(30, 50))); +} + +TEST_F(AmbientAnimationPhotoProviderTest, HandlesOnlyPortraitAvailable) { + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/10, /*height=*/30)); + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/20, /*height=*/40)); + + std::vector<scoped_refptr<ImageAsset>> all_assets = + LoadAllDynamicAssets({gfx::Size(100, 50), gfx::Size(50, 100), + gfx::Size(100, 50), gfx::Size(50, 100)}); + + std::vector<cc::SkottieFrameData> frame_data = + GetFrameDataForAssets(all_assets, /*timestamp=*/0); + EXPECT_THAT(frame_data, UnorderedElementsAre(HasImageDimensions(10, 30), + HasImageDimensions(20, 40), + HasImageDimensions(10, 30), + HasImageDimensions(20, 40))); +} + +TEST_F(AmbientAnimationPhotoProviderTest, HandlesOnlyLandscapeAvailable) { + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/30, /*height=*/10)); + AddImageToModel(gfx::test::CreateImageSkia(/*width=*/40, /*height=*/20)); + + std::vector<scoped_refptr<ImageAsset>> all_assets = + LoadAllDynamicAssets({gfx::Size(100, 50), gfx::Size(50, 100), + gfx::Size(100, 50), gfx::Size(50, 100)}); + + std::vector<cc::SkottieFrameData> frame_data = + GetFrameDataForAssets(all_assets, /*timestamp=*/0); + EXPECT_THAT(frame_data, UnorderedElementsAre(HasImageDimensions(30, 10), + HasImageDimensions(40, 20), + HasImageDimensions(30, 10), + HasImageDimensions(40, 20))); +} + } // namespace ash
diff --git a/ash/ambient/ui/ambient_animation_view.cc b/ash/ambient/ui/ambient_animation_view.cc index ac336b1..a38ec94a 100644 --- a/ash/ambient/ui/ambient_animation_view.cc +++ b/ash/ambient/ui/ambient_animation_view.cc
@@ -74,6 +74,8 @@ SetUseDefaultFillLayout(true); animated_image_view_ = AddChildView(std::make_unique<views::AnimatedImageView>()); + // Purely for performance reasons. Gains 3-4 fps. + animated_image_view_->SetPaintToLayer(); base::span<const uint8_t> lottie_data_bytes = base::as_bytes(base::make_span(static_resources_->GetLottieData())); // Create a serializable SkottieWrapper since the SkottieWrapper may have to
diff --git a/ash/app_list/views/search_box_view_unittest.cc b/ash/app_list/views/search_box_view_unittest.cc index c37edc4..dc1e640 100644 --- a/ash/app_list/views/search_box_view_unittest.cc +++ b/ash/app_list/views/search_box_view_unittest.cc
@@ -914,27 +914,6 @@ view()->ProcessAutocomplete(GetFirstResultView()); } - // Expect the entire autocomplete suggestion if |should_autocomplete| is true, - // expect only typed characters otherwise. - void ExpectAutocompleteSuggestion(bool should_autocomplete) { - if (should_autocomplete) { - // Search box autocomplete suggestion is accepted, but it should not - // trigger another query, thus it is not reflected in Search Model. - EXPECT_EQ(u"hello world!", view()->search_box()->GetText()); - EXPECT_EQ(u"he", GetSearchModel()->search_box()->text()); - } else { - // Search box autocomplete suggestion is removed and is reflected in - // SearchModel. - EXPECT_EQ(view()->search_box()->GetText(), - GetSearchModel()->search_box()->text()); - EXPECT_EQ(u"he", view()->search_box()->GetText()); - // ProcessAutocomplete should be a no-op. - ProcessAutocomplete(); - // The autocomplete suggestion should still not be present. - EXPECT_EQ(u"he", view()->search_box()->GetText()); - } - } - // Sets up the test by creating a SearchResult and displaying an autocomplete // suggestion. void SetupAutocompleteBehaviorTest() { @@ -948,74 +927,6 @@ KeyPress(ui::VKEY_E); ProcessAutocomplete(); } - - // Clears all existing text from search_box() and all existing SearchResults - // from results(). - void ResetAutocompleteBehaviorTest() { - view()->search_box()->SetText(std::u16string()); - results()->RemoveAll(); - } - - // Test a GestureEvent's autocomplete behavior according to - // |should_autocomplete|. Expect the entire autocomplete suggestion if - // |should_autocomplete| is true, expect only typed characters otherwise. - void TestGestureEvent(const ui::GestureEvent& gesture_event, - bool should_autocomplete) { - SetupAutocompleteBehaviorTest(); - // Forward |gesture_event| to HandleGestureEvent() directly because we - // cannot test GestureEvents properly due to not having ash dependencies. - // Static cast to TextfieldController because HandleGestureEvent() is - // private in SearchBoxView. TODO(crbug.com/878984): Derive - // SearchBoxViewTest from AshTestBase in order to test events using - // EventGenerator instead. - static_cast<views::TextfieldController*>(view())->HandleGestureEvent( - view()->search_box(), gesture_event); - ExpectAutocompleteSuggestion(should_autocomplete); - // Reset search box text and SearchResults for next test. - ResetAutocompleteBehaviorTest(); - } - - // Test a KeyEvent's autocomplete behavior according to |should_autocomplete|. - // Expect the entire autocomplete suggestion if |should_autocomplete| is true, - // expect only typed characters otherwise. - void TestKeyEvent(const ui::KeyEvent& key_event, bool should_autocomplete) { - SetupAutocompleteBehaviorTest(); - // TODO(crbug.com/878984): Change KeyPress() to use EventGenerator::PressKey - // instead. - if (key_event.key_code() == ui::VKEY_BACK) { - // Use KeyPress() to mimic backspace. HandleKeyEvent() will not delete the - // text. - KeyPress(key_event.key_code()); - } else { - // Forward |key_event| to HandleKeyEvent(). We use HandleKeyEvent() - // because KeyPress() will replace the existing highlighted text. Static - // cast to TextfieldController because HandleGestureEvent() is private in - // SearchBoxView. - static_cast<views::TextfieldController*>(view())->HandleKeyEvent( - view()->search_box(), key_event); - } - ExpectAutocompleteSuggestion(should_autocomplete); - // Reset search box text and SearchResults for next test. - ResetAutocompleteBehaviorTest(); - } - - // Test a MouseEvent's autocomplete behavior according to - // |should_autocomplete|. Expect the entire autocomplete suggestion if - // |should_autocomplete| is true, expect only typed characters otherwise. - void TestMouseEvent(const ui::MouseEvent& mouse_event, - bool should_autocomplete) { - SetupAutocompleteBehaviorTest(); - // Forward |mouse_event| to HandleMouseEvent() directly because we cannot - // test MouseEvents properly due to not having ash dependencies. Static cast - // to TextfieldController because HandleGestureEvent() is a private method - // in SearchBoxView. TODO(crbug.com/878984): Derive SearchBoxViewTest from - // AshTestBase in order to test events using EventGenerator instead. - static_cast<views::TextfieldController*>(view())->HandleMouseEvent( - view()->search_box(), mouse_event); - ExpectAutocompleteSuggestion(should_autocomplete); - // Reset search box text and SearchResults for next test. - ResetAutocompleteBehaviorTest(); - } }; // Run search box view autocomplete tests with and without productivity launcher @@ -1160,14 +1071,41 @@ // Tests that autocomplete suggestion is accepted and displayed in SearchModel // after clicking or tapping on the search box. -TEST_P(SearchBoxViewAutocompleteTest, SearchBoxAcceptsAutocompleteForClickTap) { - TestMouseEvent(ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), - gfx::Point(), ui::EventTimeForNow(), 0, 0), - true); - TestGestureEvent( - ui::GestureEvent(0, 0, 0, ui::EventTimeForNow(), - ui::GestureEventDetails(ui::ET_GESTURE_TAP)), - true); +TEST_P(SearchBoxViewAutocompleteTest, SearchBoxAcceptsAutocompleteForClick) { + SetupAutocompleteBehaviorTest(); + + ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(), + ui::EventTimeForNow(), 0, 0); + // Forward |mouse_event| to HandleMouseEvent() directly because we cannot + // test MouseEvents properly due to not having ash dependencies. Static cast + // to TextfieldController because HandleGestureEvent() is a private method + // in SearchBoxView. TODO(crbug.com/878984): Derive SearchBoxViewTest from + // AshTestBase in order to test events using EventGenerator instead. + static_cast<views::TextfieldController*>(view())->HandleMouseEvent( + view()->search_box(), mouse_event); + // Search box autocomplete suggestion is accepted, but it should not + // trigger another query, thus it is not reflected in Search Model. + EXPECT_EQ(u"hello world!", view()->search_box()->GetText()); + EXPECT_EQ(u"he", GetSearchModel()->search_box()->text()); +} + +TEST_P(SearchBoxViewAutocompleteTest, SearchBoxAcceptsAutocompleteForTap) { + SetupAutocompleteBehaviorTest(); + + ui::GestureEvent gesture_event(0, 0, 0, ui::EventTimeForNow(), + ui::GestureEventDetails(ui::ET_GESTURE_TAP)); + // Forward |gesture_event| to HandleGestureEvent() directly because we + // cannot test GestureEvents properly due to not having ash dependencies. + // Static cast to TextfieldController because HandleGestureEvent() is + // private in SearchBoxView. TODO(crbug.com/878984): Derive + // SearchBoxViewTest from AshTestBase in order to test events using + // EventGenerator instead. + static_cast<views::TextfieldController*>(view())->HandleGestureEvent( + view()->search_box(), gesture_event); + // Search box autocomplete suggestion is accepted, but it should not + // trigger another query, thus it is not reflected in Search Model. + EXPECT_EQ(u"hello world!", view()->search_box()->GetText()); + EXPECT_EQ(u"he", GetSearchModel()->search_box()->text()); } // Tests that autocomplete is not handled if IME is using composition text.
diff --git a/ash/capture_mode/capture_mode_camera_controller.cc b/ash/capture_mode/capture_mode_camera_controller.cc index 7f684eea6..18861e8e 100644 --- a/ash/capture_mode/capture_mode_camera_controller.cc +++ b/ash/capture_mode/capture_mode_camera_controller.cc
@@ -15,6 +15,7 @@ #include "base/callback_helpers.h" #include "base/check.h" #include "base/strings/stringprintf.h" +#include "base/time/time.h" #include "media/capture/video/video_capture_device_descriptor.h" #include "ui/views/widget/widget.h" @@ -22,6 +23,11 @@ namespace { +// The maximum amount of time we allow a `selected_camera_` to remain +// disconnected before we consider it gone forever, and we clear its ID from +// `selected_camera_`. +constexpr base::TimeDelta kDisconnectionGracePeriod = base::Seconds(10); + // Defines a map type to map a camera model ID (or display name) to the number // of cameras of that model that are currently connected. using ModelIdToCountMap = std::map<std::string, int>; @@ -161,7 +167,15 @@ } void CaptureModeCameraController::SetSelectedCamera(CameraId camera_id) { + if (selected_camera_ == camera_id) + return; + selected_camera_ = std::move(camera_id); + camera_reconnect_timer_.Stop(); + + for (auto& observer : observers_) + observer.OnSelectedCameraChanged(selected_camera_); + RefreshCameraPreview(); } @@ -233,8 +247,30 @@ } void CaptureModeCameraController::RefreshCameraPreview() { - const CameraInfo* camera_info = GetCameraInfoForPreview(); - if (!camera_info) { + bool create_or_keep_widget = false; + if (selected_camera_.is_valid()) { + if (const CameraInfo* camera_info = + GetCameraInfoById(selected_camera_, available_cameras_); + camera_info) { + // When a selected camera becomes available, we stop any grace period + // timer (if any), and decide whether to show or hide the preview widget + // based on the current value of `should_show_preview_`. + camera_reconnect_timer_.Stop(); + create_or_keep_widget = should_show_preview_; + } else { + // Here the selected camera is disconnected, we'll give it a grace period + // just in case it may reconnect again (this helps in the case of flaky + // camera connections). + camera_reconnect_timer_.Start( + FROM_HERE, kDisconnectionGracePeriod, this, + &CaptureModeCameraController::OnSelectedCameraDisconnected); + + // TODO(afakhry): Clear the camera immediately if it gets disconnected + // during count down and before recording starts. + } + } + + if (!create_or_keep_widget) { camera_preview_widget_.reset(); camera_preview_view_ = nullptr; return; @@ -249,10 +285,13 @@ camera_preview_widget_->Show(); } -const CameraInfo* CaptureModeCameraController::GetCameraInfoForPreview() const { - if (!should_show_preview_ || !selected_camera_.is_valid()) - return nullptr; - return GetCameraInfoById(selected_camera_, available_cameras_); +void CaptureModeCameraController::OnSelectedCameraDisconnected() { + DCHECK(selected_camera_.is_valid()); + + LOG(WARNING) + << "Selected camera: " << selected_camera_.ToString() + << " remained disconnected for longer than the grace period. Clearing."; + SetSelectedCamera(CameraId()); } } // namespace ash
diff --git a/ash/capture_mode/capture_mode_camera_controller.h b/ash/capture_mode/capture_mode_camera_controller.h index d5d91d9a..9841218 100644 --- a/ash/capture_mode/capture_mode_camera_controller.h +++ b/ash/capture_mode/capture_mode_camera_controller.h
@@ -14,6 +14,7 @@ #include "base/observer_list.h" #include "base/observer_list_types.h" #include "base/system/system_monitor.h" +#include "base/timer/timer.h" #include "media/capture/video/video_capture_device_info.h" #include "mojo/public/cpp/bindings/remote.h" #include "services/video_capture/public/mojom/video_source_provider.mojom.h" @@ -105,6 +106,12 @@ // changed, and provides that list as `cameras`. virtual void OnAvailableCamerasChanged(const CameraInfoList& cameras) = 0; + // Called to notify the observer that a camera with `camera_id` was selected + // and will be used to show a camera preview when possible. + // Note that when `camera_id.is_valid()` is false, it means no camera is + // currently selected. + virtual void OnSelectedCameraChanged(const CameraId& camera_id) = 0; + protected: ~Observer() override = default; }; @@ -141,6 +148,10 @@ on_camera_list_received_for_test_ = std::move(callback); } + base::OneShotTimer* camera_reconnect_timer_for_test() { + return &camera_reconnect_timer_; + } + private: // Called to connect to the video capture services's video source provider for // the first time, or when the connection to it is lost. It also queries the @@ -161,9 +172,10 @@ // whether it's currently allowed and whether one is currently selected. void RefreshCameraPreview(); - // Returns a pointer to the CameraInfo item of the camera that should be used - // for the preview, or nullptr if no such camera exists. - const CameraInfo* GetCameraInfoForPreview() const; + // Triggered when the `camera_reconnect_timer_` fires, indicating that a + // previously `selected_camera_` remained disconnected for longer than the + // allowed grace period, and therefore it will be cleared. + void OnSelectedCameraDisconnected(); // Owned by CaptureModeController and guaranteed to be not null and to outlive // `this`. @@ -193,6 +205,12 @@ views::UniqueWidgetPtr camera_preview_widget_; CameraPreviewView* camera_preview_view_ = nullptr; + // A timer used to give a `selected_camera_` that got disconnected a grace + // period, so if it reconnects again within this period, its ID is kept around + // in `selected_camera_`, otherwise the ID is cleared, effectively resetting + // back the camera setting to "Off". + base::OneShotTimer camera_reconnect_timer_; + // Set to true when a preview of the currently selected camera (if any) should // be shown. This happens when CaptureModeSession is started or switched to // a video recording mode before recording starts. It is reset back to false
diff --git a/ash/capture_mode/capture_mode_camera_unittests.cc b/ash/capture_mode/capture_mode_camera_unittests.cc index fc4a44a..36d1729 100644 --- a/ash/capture_mode/capture_mode_camera_unittests.cc +++ b/ash/capture_mode/capture_mode_camera_unittests.cc
@@ -41,6 +41,9 @@ } int camera_change_event_count() const { return camera_change_event_count_; } + int selected_camera_change_event_count() const { + return selected_camera_change_event_count_; + } void Wait() { loop_.Run(); } @@ -50,12 +53,19 @@ loop_.Quit(); } + void OnSelectedCameraChanged(const CameraId& camera_id) override { + ++selected_camera_change_event_count_; + } + private: base::RunLoop loop_; // Tracks the number of times the observer call `OnAvailableCamerasChanged()` // was triggered. int camera_change_event_count_ = 0; + + // Tracks the number of times `OnSelectedCameraChanged()` was triggered. + int selected_camera_change_event_count_ = 0; }; } // namespace @@ -77,20 +87,41 @@ void AddFakeCamera(const std::string& device_id, const std::string& display_name, const std::string& model_id) { + CameraDevicesChangeWaiter waiter; GetTestDelegate()->video_source_provider()->AddFakeCamera( device_id, display_name, model_id); + waiter.Wait(); } void RemoveFakeCamera(const std::string& device_id) { + CameraDevicesChangeWaiter waiter; GetTestDelegate()->video_source_provider()->RemoveFakeCamera(device_id); + waiter.Wait(); } void AddDefaultCamera() { + CameraDevicesChangeWaiter waiter; AddFakeCamera(kDefaultCameraDeviceId, kDefaultCameraDisplayName, kDefaultCameraModelId); + waiter.Wait(); } - void RemoveDefaultCamera() { RemoveFakeCamera(kDefaultCameraDeviceId); } + void RemoveDefaultCamera() { + CameraDevicesChangeWaiter waiter; + RemoveFakeCamera(kDefaultCameraDeviceId); + waiter.Wait(); + } + + // Adds the default camera, sets it as the selected camera, then removes it, + // which triggers the camera disconnection grace period. Returns a pointer to + // the `CaptureModeCameraController`. + CaptureModeCameraController* AddAndRemoveCameraAndTriggerGracePeriod() { + AddDefaultCamera(); + auto* camera_controller = GetCameraController(); + camera_controller->SetSelectedCamera(CameraId(kDefaultCameraModelId, 1)); + RemoveDefaultCamera(); + return camera_controller; + } private: base::test::ScopedFeatureList scoped_feature_list_; @@ -108,11 +139,7 @@ const std::string device_id = "/dev/video0"; const std::string display_name = "Integrated Webcam"; const std::string model_id = "0123:4567"; - { - CameraDevicesChangeWaiter waiter; - AddFakeCamera(device_id, display_name, model_id); - waiter.Wait(); - } + AddFakeCamera(device_id, display_name, model_id); EXPECT_EQ(1u, camera_controller->available_cameras().size()); EXPECT_TRUE(camera_controller->available_cameras()[0].camera_id.is_valid()); @@ -125,11 +152,7 @@ EXPECT_FALSE(camera_controller->should_show_preview()); EXPECT_FALSE(camera_controller->camera_preview_widget()); - { - CameraDevicesChangeWaiter waiter; - RemoveFakeCamera(device_id); - waiter.Wait(); - } + RemoveFakeCamera(device_id); EXPECT_TRUE(camera_controller->available_cameras().empty()); EXPECT_FALSE(camera_controller->should_show_preview()); @@ -152,11 +175,7 @@ camera_controller->SetShouldShowPreview(true); EXPECT_FALSE(camera_controller->camera_preview_widget()); - { - CameraDevicesChangeWaiter waiter; - AddDefaultCamera(); - waiter.Wait(); - } + AddDefaultCamera(); EXPECT_EQ(1u, camera_controller->available_cameras().size()); EXPECT_FALSE(camera_controller->camera_preview_widget()); @@ -177,11 +196,7 @@ // The selected camera becomes available while `should_show_preview_` is still // true. The preview should show in this case. - { - CameraDevicesChangeWaiter waiter; - AddDefaultCamera(); - waiter.Wait(); - } + AddDefaultCamera(); EXPECT_TRUE(camera_controller->camera_preview_widget()); // Clearing the selected camera should hide the preview. @@ -196,11 +211,7 @@ const std::string device_id_1 = "/dev/video0"; const std::string display_name = "Integrated Webcam"; const std::string model_id = "0123:4567"; - { - CameraDevicesChangeWaiter waiter; - AddFakeCamera(device_id_1, display_name, model_id); - waiter.Wait(); - } + AddFakeCamera(device_id_1, display_name, model_id); const auto& available_cameras = camera_controller->available_cameras(); EXPECT_EQ(1u, available_cameras.size()); @@ -211,11 +222,7 @@ // Adding a new camera of the same model should be correctly tracked with a // different ID. const std::string device_id_2 = "/dev/video1"; - { - CameraDevicesChangeWaiter waiter; - AddFakeCamera(device_id_2, display_name, model_id); - waiter.Wait(); - } + AddFakeCamera(device_id_2, display_name, model_id); EXPECT_EQ(2u, available_cameras.size()); EXPECT_EQ(2, available_cameras[1].camera_id.number()); @@ -229,11 +236,7 @@ const std::string device_id = "/dev/video0"; const std::string display_name = "Integrated Webcam"; - { - CameraDevicesChangeWaiter waiter; - AddFakeCamera(device_id, display_name, /*model_id=*/""); - waiter.Wait(); - } + AddFakeCamera(device_id, display_name, /*model_id=*/""); // The camera's display name should be used instead of a model ID when it's // missing. @@ -258,4 +261,98 @@ } } +TEST_F(CaptureModeCameraTest, DisconnectSelectedCamera) { + AddDefaultCamera(); + auto* camera_controller = GetCameraController(); + const CameraId camera_id(kDefaultCameraModelId, 1); + camera_controller->SetSelectedCamera(camera_id); + + // Disconnect a selected camera, and expect that the grace period timer is + // running. + RemoveDefaultCamera(); + base::OneShotTimer* timer = + camera_controller->camera_reconnect_timer_for_test(); + EXPECT_TRUE(timer->IsRunning()); + EXPECT_EQ(camera_id, camera_controller->selected_camera()); + + // When the timer fires before the camera gets reconnected, the selected + // camera ID is cleared. + timer->FireNow(); + EXPECT_FALSE(camera_controller->selected_camera().is_valid()); + EXPECT_FALSE(timer->IsRunning()); +} + +TEST_F(CaptureModeCameraTest, SelectUnavailableCameraDuringGracePeriod) { + auto* camera_controller = AddAndRemoveCameraAndTriggerGracePeriod(); + base::OneShotTimer* timer = + camera_controller->camera_reconnect_timer_for_test(); + EXPECT_TRUE(timer->IsRunning()); + + // Selecting an unavailable camera during the grace period should keep the + // timer running for another grace period. + const CameraId new_camera_id("Different Camera", 1); + camera_controller->SetSelectedCamera(new_camera_id); + EXPECT_TRUE(timer->IsRunning()); + EXPECT_EQ(new_camera_id, camera_controller->selected_camera()); + + // Once the timer fires the new ID will also be cleared. + timer->FireNow(); + EXPECT_FALSE(camera_controller->selected_camera().is_valid()); + EXPECT_FALSE(timer->IsRunning()); +} + +TEST_F(CaptureModeCameraTest, SelectAvailableCameraDuringGracePeriod) { + const std::string device_id = "/dev/video0"; + const std::string display_name = "Integrated Webcam"; + const CameraId available_camera_id(display_name, 1); + AddFakeCamera(device_id, display_name, /*model_id=*/""); + + // This adds the default camera as the selected one, and removes it triggering + // a grace period. + auto* camera_controller = AddAndRemoveCameraAndTriggerGracePeriod(); + base::OneShotTimer* timer = + camera_controller->camera_reconnect_timer_for_test(); + EXPECT_TRUE(timer->IsRunning()); + + // Selecting the available camera during the grace period should stop the + // timer immediately. + camera_controller->SetSelectedCamera(available_camera_id); + EXPECT_FALSE(timer->IsRunning()); + EXPECT_EQ(available_camera_id, camera_controller->selected_camera()); +} + +// This tests simulates a flaky camera connection. +TEST_F(CaptureModeCameraTest, ReconnectDuringGracePeriod) { + auto* camera_controller = AddAndRemoveCameraAndTriggerGracePeriod(); + camera_controller->SetShouldShowPreview(true); + base::OneShotTimer* timer = + camera_controller->camera_reconnect_timer_for_test(); + EXPECT_TRUE(timer->IsRunning()); + EXPECT_FALSE(camera_controller->camera_preview_widget()); + + // Readd the camera during the grace period, the timer should stop, and the + // preview should reshow. + AddDefaultCamera(); + EXPECT_FALSE(timer->IsRunning()); + EXPECT_TRUE(camera_controller->camera_preview_widget()); +} + +TEST_F(CaptureModeCameraTest, SelectedCameraChangedObserver) { + AddDefaultCamera(); + auto* camera_controller = GetCameraController(); + const CameraId camera_id(kDefaultCameraModelId, 1); + + CameraDevicesChangeWaiter observer; + camera_controller->SetSelectedCamera(camera_id); + EXPECT_EQ(1, observer.selected_camera_change_event_count()); + + // Selecting the same camera ID again should not trigger an observer call. + camera_controller->SetSelectedCamera(camera_id); + EXPECT_EQ(1, observer.selected_camera_change_event_count()); + + // Clearing the ID should. + camera_controller->SetSelectedCamera(CameraId()); + EXPECT_EQ(2, observer.selected_camera_change_event_count()); +} + } // namespace ash
diff --git a/ash/components/arc/arc_features.cc b/ash/components/arc/arc_features.cc index 2e4d84453a..c1942b41 100644 --- a/ash/components/arc/arc_features.cc +++ b/ash/components/arc/arc_features.cc
@@ -13,7 +13,7 @@ // Controls experimental Compat snap feature for ARC. const base::Feature kCompatSnapFeature{"ArcCompatSnapFeature", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; // Controls experimental Custom Tabs feature for ARC. const base::Feature kCustomTabsExperimentFeature{
diff --git a/ash/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc b/ash/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc index 0a1c5991..b9b1ccf 100644 --- a/ash/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc +++ b/ash/components/arc/compat_mode/arc_resize_lock_manager_unittest.cc
@@ -452,8 +452,6 @@ // Tests that compatible window snapping is properly enabled for resize-locked // windows. TEST_F(ArcResizeLockManagerTest, TestCompatWindowSnap) { - base::test::ScopedFeatureList feature_list{arc::kCompatSnapFeature}; - auto arc_window = CreateFakeWindow(true); arc_window->SetProperty(ash::kAppIDKey, std::string("app-id")); @@ -479,6 +477,9 @@ // Tests that compatible window snapping is properly disabled if the flag is // disabled. TEST_F(ArcResizeLockManagerTest, TestCompatWindowSnapWithFlagDisabled) { + base::test::ScopedFeatureList feature_list; + feature_list.InitAndDisableFeature({arc::kCompatSnapFeature}); + auto arc_window = CreateFakeWindow(true); arc_window->SetProperty(ash::kAppIDKey, std::string("app-id")); arc_window->SetProperty(aura::client::kResizeBehaviorKey,
diff --git a/ash/components/arc/mojom/app.mojom b/ash/components/arc/mojom/app.mojom index 9c439e8..5b848a0 100644 --- a/ash/components/arc/mojom/app.mojom +++ b/ash/components/arc/mojom/app.mojom
@@ -82,8 +82,8 @@ // installed on the browser side. [MinVersion=38] WebAppInfo? web_app_info; - // Deprecated in favour of |permission_states| - [MinVersion=41] map<AppPermission, bool>? permissions; + // Deprecated and unused in favour of |permission_states| + [MinVersion=41] map<AppPermission, bool>? deprecated_permissions; [MinVersion=43] map<AppPermission, PermissionState>? permission_states; };
diff --git a/ash/components/arc/session/arc_vm_client_adapter.cc b/ash/components/arc/session/arc_vm_client_adapter.cc index 751310d..6a91c94 100644 --- a/ash/components/arc/session/arc_vm_client_adapter.cc +++ b/ash/components/arc/session/arc_vm_client_adapter.cc
@@ -105,6 +105,8 @@ constexpr base::TimeDelta kConnectSleepDurationInitial = base::Milliseconds(100); +constexpr const char kEmptyDiskPath[] = "/dev/null"; + absl::optional<base::TimeDelta> g_connect_timeout_limit_for_testing; absl::optional<base::TimeDelta> g_connect_sleep_duration_initial_for_testing; absl::optional<int> g_boot_notification_server_fd; @@ -401,15 +403,36 @@ disk_image->set_block_size(kBlockSize); // Add /run/imageloader/.../android_demo_apps.squash as /dev/block/vdc if - // needed. + // needed. If it's not needed we pass /dev/null so that /dev/block/vdc + // always corresponds to the demo image. + disk_image = request.add_disks(); + disk_image->set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO); + disk_image->set_writable(false); + disk_image->set_do_mount(true); if (!demo_session_apps_path.empty()) { - disk_image = request.add_disks(); disk_image->set_path(demo_session_apps_path.value()); - disk_image->set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO); - disk_image->set_writable(false); - disk_image->set_do_mount(true); if (should_set_blocksize) disk_image->set_block_size(kBlockSize); + } else { + // This should never be mounted as it's only mounted if + // ro.boot.arc_demo_mode is set. + disk_image->set_path(kEmptyDiskPath); + } + + // Add /opt/google/vms/android/apex/payload.img as /dev/block/vdd if + // needed. If it's not needed we pass /dev/null so that /dev/block/vdd + // always corresponds to the block apex composite disk. + disk_image = request.add_disks(); + disk_image->set_image_type(vm_tools::concierge::DISK_IMAGE_AUTO); + disk_image->set_writable(false); + disk_image->set_do_mount(true); + if (!file_system_status.block_apex_path().empty()) { + disk_image->set_path(file_system_status.block_apex_path().value()); + } else { + // Android will not mount this is the system property + // apexd.payload_metadata.path is not set, and it should + // always be set if the block apex payload exists. + disk_image->set_path(kEmptyDiskPath); } // Add Android fstab. @@ -450,6 +473,7 @@ if (vm_ram_mib > kVmRamMinMib) { request.set_memory_mib(vm_ram_mib); + VLOG(1) << "VmMemorySize is enabled. memory_mib=" << vm_ram_mib; } else { VLOG(1) << "VmMemorySize is enabled, but computed size is " << "min(" << ram_mib << " + " << shift_mib << "," << max_mib @@ -459,18 +483,25 @@ } else { VLOG(1) << "VmMemorySize is enabled, but GetSystemMemoryInfo failed."; } + } else { + VLOG(1) << "VmMemorySize is disabled."; } // Specify balloon policy. if (base::FeatureList::IsEnabled(kVmBalloonPolicy)) { vm_tools::concierge::BalloonPolicyOptions* balloon_policy = request.mutable_balloon_policy(); - balloon_policy->set_moderate_target_cache( - static_cast<int64_t>(kVmBalloonPolicyModerateKiB.Get()) * 1024); - balloon_policy->set_critical_target_cache( - static_cast<int64_t>(kVmBalloonPolicyCriticalKiB.Get()) * 1024); - balloon_policy->set_reclaim_target_cache( - static_cast<int64_t>(kVmBalloonPolicyReclaimKiB.Get()) * 1024); + const int64_t moderate_kib = kVmBalloonPolicyModerateKiB.Get(); + const int64_t critical_kib = kVmBalloonPolicyCriticalKiB.Get(); + const int64_t reclaim_kib = kVmBalloonPolicyReclaimKiB.Get(); + balloon_policy->set_moderate_target_cache(moderate_kib * 1024); + balloon_policy->set_critical_target_cache(critical_kib * 1024); + balloon_policy->set_reclaim_target_cache(reclaim_kib * 1024); + VLOG(1) << "Use LimitCacheBalloonPolicy. ModerateKiB=" << moderate_kib + << ", CriticalKiB=" << critical_kib + << ", ReclaimKiB=" << reclaim_kib; + } else { + VLOG(1) << "Use BalanceAvailableBalloonPolicy"; } return request;
diff --git a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc index 5917e5d5..d2e3f4f 100644 --- a/ash/components/arc/session/arc_vm_client_adapter_unittest.cc +++ b/ash/components/arc/session/arc_vm_client_adapter_unittest.cc
@@ -614,6 +614,10 @@ return boot_server_.get(); } + void set_block_apex_path(base::FilePath block_apex_path) { + block_apex_path_ = block_apex_path; + } + void set_host_rootfs_writable(bool host_rootfs_writable) { host_rootfs_writable_ = host_rootfs_writable; } @@ -629,6 +633,7 @@ private: void RewriteStatus(FileSystemStatus* status) { + status->set_block_apex_path_for_testing(block_apex_path_); status->set_host_rootfs_writable_for_testing(host_rootfs_writable_); status->set_system_image_ext_format_for_testing(system_image_ext_format_); } @@ -642,6 +647,7 @@ ArcServiceManager arc_service_manager_; // Variables to override the value in FileSystemStatus. + base::FilePath block_apex_path_; bool host_rootfs_writable_; bool system_image_ext_format_; @@ -2129,6 +2135,38 @@ EXPECT_FALSE(request.has_balloon_policy()); } +// Test that the request passes an empty disk for the demo image +// or the block apex composite disk when they are not present. +// There should be two empty disks (/dev/block/vdc and /dev/block/vdd) +// and they should have path /dev/null. +TEST_F(ArcVmClientAdapterTest, ArcVmEmptyVirtualDisksExist) { + StartMiniArc(); + + auto request = GetTestConciergeClient()->start_arc_vm_request(); + EXPECT_EQ(request.disks(1).path(), "/dev/null"); + EXPECT_EQ(request.disks(2).path(), "/dev/null"); +} + +// Test that block apex disk path exists when the composite disk payload +// exists. +TEST_F(ArcVmClientAdapterTest, ArcVmBlockApexDiskExists) { + constexpr const char path[] = "/opt/google/vms/android/apex/payload.img"; + set_block_apex_path(base::FilePath(path)); + StartMiniArc(); + auto request = GetTestConciergeClient()->start_arc_vm_request(); + EXPECT_TRUE(base::Contains(request.disks(), path, + [](const auto& p) { return p.path(); })); +} + +// Test that the block apex disk path isn't included when it doesn't exist. +TEST_F(ArcVmClientAdapterTest, ArcVmNoBlockApexDisk) { + constexpr const char path[] = "/opt/google/vms/android/apex/payload.img"; + StartMiniArc(); + auto request = GetTestConciergeClient()->start_arc_vm_request(); + EXPECT_FALSE(base::Contains(request.disks(), path, + [](const auto& p) { return p.path(); })); +} + // Tests that OnConnectionReady() calls the MakeRtVcpu call D-Bus method. TEST_F(ArcVmClientAdapterTest, OnConnectionReady) { StartParams start_params(GetPopulatedStartParams());
diff --git a/ash/components/arc/session/file_system_status.cc b/ash/components/arc/session/file_system_status.cc index 411c5e0..607bd98 100644 --- a/ash/components/arc/session/file_system_status.cc +++ b/ash/components/arc/session/file_system_status.cc
@@ -24,6 +24,10 @@ constexpr const char kKernel[] = "vmlinux"; constexpr const char kRootFs[] = "system.raw.img"; constexpr const char kVendorImage[] = "vendor.raw.img"; +// Path to block apex payload. This is a composite disk containing +// Android apexes which will be mounted as block devices. +// This is a relative path starting from kBuiltinPath. +constexpr const char kBlockApexPath[] = "apex/payload.img"; } // namespace @@ -39,7 +43,11 @@ guest_kernel_path_(base::FilePath(kBuiltinPath).Append(kKernel)), fstab_path_(kFstabPath), is_system_image_ext_format_(IsSystemImageExtFormat(system_image_path_)), - has_adbd_json_(base::PathExists(base::FilePath(kAdbdJson))) {} + has_adbd_json_(base::PathExists(base::FilePath(kAdbdJson))) { + auto apex_path = base::FilePath(kBuiltinPath).Append(kBlockApexPath); + block_apex_path_ = + base::PathExists(apex_path) ? apex_path : base::FilePath(""); +} // static bool FileSystemStatus::IsHostRootfsWritable() {
diff --git a/ash/components/arc/session/file_system_status.h b/ash/components/arc/session/file_system_status.h index d2901c3a..f313bb8 100644 --- a/ash/components/arc/session/file_system_status.h +++ b/ash/components/arc/session/file_system_status.h
@@ -34,6 +34,7 @@ const base::FilePath& vendor_image_path() const { return vendor_image_path_; } const base::FilePath& guest_kernel_path() const { return guest_kernel_path_; } const base::FilePath& fstab_path() const { return fstab_path_; } + const base::FilePath& block_apex_path() const { return block_apex_path_; } // Setters for testing. void set_host_rootfs_writable_for_testing(bool is_host_rootfs_writable) { @@ -58,6 +59,9 @@ void set_fstab_path_for_testing(const base::FilePath& fstab_path) { fstab_path_ = fstab_path; } + void set_block_apex_path_for_testing(const base::FilePath& block_apex_path) { + block_apex_path_ = block_apex_path; + } static bool IsSystemImageExtFormatForTesting(const base::FilePath& path) { return IsSystemImageExtFormat(path); @@ -78,6 +82,7 @@ base::FilePath vendor_image_path_; base::FilePath guest_kernel_path_; base::FilePath fstab_path_; + base::FilePath block_apex_path_; bool is_system_image_ext_format_; bool has_adbd_json_; };
diff --git a/ash/components/phonehub/notification.cc b/ash/components/phonehub/notification.cc index ad4aa4e..ff7783d 100644 --- a/ash/components/phonehub/notification.cc +++ b/ash/components/phonehub/notification.cc
@@ -9,6 +9,7 @@ #include "base/base64.h" #include "base/containers/flat_map.h" #include "base/logging.h" +#include "base/strings/utf_string_conversions.h" namespace ash { namespace phonehub { @@ -68,7 +69,10 @@ const base::Value* visible_app_name_value = value.FindPath(kVisibleAppName); std::u16string visible_app_name_string_value; - visible_app_name_value->GetAsString(&visible_app_name_string_value); + if (visible_app_name_value->is_string()) { + visible_app_name_string_value = + base::UTF8ToUTF16(visible_app_name_value->GetString()); + } std::string icon_str; base::Base64Decode(*(value.FindStringPath(kIcon)), &icon_str);
diff --git a/ash/constants/ash_features.cc b/ash/constants/ash_features.cc index 991e4bc..6659cba 100644 --- a/ash/constants/ash_features.cc +++ b/ash/constants/ash_features.cc
@@ -121,10 +121,6 @@ const base::Feature kArcManagedAdbSideloadingSupport{ "ArcManagedAdbSideloadingSupport", base::FEATURE_DISABLED_BY_DEFAULT}; -// Controls whether to enable assistive autocorrect. -const base::Feature kAssistAutoCorrect{"AssistAutoCorrect", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Controls whether to enable enhanced assistive emoji suggestions. const base::Feature kAssistEmojiEnhanced{"AssistEmojiEnhanced", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -665,6 +661,10 @@ // Enable ChromeOS FuseBox service. const base::Feature kFuseBox{"FuseBox", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enable GuestOS integration with the files app. +const base::Feature kGuestOsFiles{"GuestOsFiles", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables or disables handle of `closeView` message from Gaia. The message is // supposed to end the flow. const base::Feature kGaiaCloseViewMessage{"GaiaCloseViewMessage", @@ -768,20 +768,11 @@ const base::Feature kVirtualKeyboardDarkMode{"VirtualKeyboardDarkMode", base::FEATURE_ENABLED_BY_DEFAULT}; -// If enabled, options page for each input method will be opened in ChromeOS -// settings. Otherwise it will be opened in a new web page in Chrome browser. -const base::Feature kImeOptionsInSettings{"ImeOptionsInSettings", - base::FEATURE_ENABLED_BY_DEFAULT}; - // If enabled, used to configure the heuristic rules for some advanced IME // features (e.g. auto-correct). const base::Feature kImeRuleConfig{"ImeRuleConfig", base::FEATURE_DISABLED_BY_DEFAULT}; -// Enable or disable system emoji picker. -const base::Feature kImeSystemEmojiPicker{"SystemEmojiPicker", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Enable or disable system emoji picker falling back to clipboard. const base::Feature kImeSystemEmojiPickerClipboard{ "SystemEmojiPickerClipboard", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -1607,6 +1598,10 @@ return base::FeatureList::IsEnabled(kGaiaReauthEndpoint); } +bool IsGuestOsFilesEnabled() { + return base::FeatureList::IsEnabled(kGuestOsFiles); +} + bool IsHideArcMediaNotificationsEnabled() { return base::FeatureList::IsEnabled(kHideArcMediaNotifications); }
diff --git a/ash/constants/ash_features.h b/ash/constants/ash_features.h index 8df8130..2af085f 100644 --- a/ash/constants/ash_features.h +++ b/ash/constants/ash_features.h
@@ -254,6 +254,7 @@ COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kFullscreenAlertBubble; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kFuseBox; +COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kGuestOsFiles; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kGaiaCloseViewMessage; COMPONENT_EXPORT(ASH_CONSTANTS) extern const base::Feature kGaiaReauthEndpoint;
diff --git a/ash/keyboard/virtual_keyboard_controller.cc b/ash/keyboard/virtual_keyboard_controller.cc index 8def11e..e5ea375 100644 --- a/ash/keyboard/virtual_keyboard_controller.cc +++ b/ash/keyboard/virtual_keyboard_controller.cc
@@ -57,12 +57,6 @@ UpdateDevices(); // Set callback to show the emoji panel - if (!base::FeatureList::IsEnabled( - chromeos::features::kImeSystemEmojiPicker)) { - ui::SetShowEmojiKeyboardCallback(base::BindRepeating( - &VirtualKeyboardController::ForceShowKeyboardWithKeyset, - base::Unretained(this), input_method::ImeKeyset::kEmoji)); - } ui::SetTabletModeShowEmojiKeyboardCallback(base::BindRepeating( &VirtualKeyboardController::ForceShowKeyboardWithKeyset, base::Unretained(this), input_method::ImeKeyset::kEmoji));
diff --git a/ash/login/ui/views_utils.h b/ash/login/ui/views_utils.h index 49e1a09..a51c332 100644 --- a/ash/login/ui/views_utils.h +++ b/ash/login/ui/views_utils.h
@@ -21,13 +21,13 @@ namespace login_views_utils { // The most used font size on login/lock screen. -constexpr inline int kLoginDefaultFontSize = 13; +inline constexpr int kLoginDefaultFontSize = 13; // The most used font on login/lock screen. -constexpr inline char kLoginDefaultFontName[] = "Roboto"; -constexpr inline char kGoogleSansFont[] = "Google Sans"; +inline constexpr char kLoginDefaultFontName[] = "Roboto"; +inline constexpr char kGoogleSansFont[] = "Google Sans"; -constexpr inline int kDefaultLineHeight = 20; +inline constexpr int kDefaultLineHeight = 20; // Helper function to get default font list for login/lock screen text label. // It is slightly different from views::Label::GetDefaultFontList since the
diff --git a/ash/policy/policy_recommendation_restorer_unittest.cc b/ash/policy/policy_recommendation_restorer_unittest.cc index d2af7c0f..401887e 100644 --- a/ash/policy/policy_recommendation_restorer_unittest.cc +++ b/ash/policy/policy_recommendation_restorer_unittest.cc
@@ -91,7 +91,7 @@ EXPECT_TRUE(pref->HasUserSetting()); const base::Value* value = pref->GetValue(); ASSERT_TRUE(value); - EXPECT_TRUE(expected_value.Equals(value)); + EXPECT_EQ(expected_value, *value); } void VerifyPrefsFollowUser() const { @@ -117,7 +117,7 @@ EXPECT_FALSE(pref->HasUserSetting()); const base::Value* value = pref->GetValue(); ASSERT_TRUE(value); - EXPECT_TRUE(expected_value.Equals(value)); + EXPECT_EQ(expected_value, *value); } void VerifyPrefsFollowRecommendation() const {
diff --git a/ash/quick_pair/fast_pair_handshake/fast_pair_data_encryptor.h b/ash/quick_pair/fast_pair_handshake/fast_pair_data_encryptor.h index 68e3126..f1ac695 100644 --- a/ash/quick_pair/fast_pair_handshake/fast_pair_data_encryptor.h +++ b/ash/quick_pair/fast_pair_handshake/fast_pair_data_encryptor.h
@@ -15,7 +15,7 @@ #include "base/callback.h" #include "third_party/abseil-cpp/absl/types/optional.h" -constexpr inline int kBlockSizeBytes = 16; +inline constexpr int kBlockSizeBytes = 16; namespace ash { namespace quick_pair {
diff --git a/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client.h b/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client.h index c40ad73..d48ee7ee 100644 --- a/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client.h +++ b/ash/quick_pair/fast_pair_handshake/fast_pair_gatt_service_client.h
@@ -7,7 +7,7 @@ #include "device/bluetooth/bluetooth_adapter.h" -constexpr inline int kBlockByteSize = 16; +inline constexpr int kBlockByteSize = 16; namespace ash { namespace quick_pair {
diff --git a/ash/quick_pair/fast_pair_handshake/fast_pair_key_pair.h b/ash/quick_pair/fast_pair_handshake/fast_pair_key_pair.h index 1050e22..e25edfcf 100644 --- a/ash/quick_pair/fast_pair_handshake/fast_pair_key_pair.h +++ b/ash/quick_pair/fast_pair_handshake/fast_pair_key_pair.h
@@ -10,8 +10,8 @@ #include <array> -constexpr inline int kPrivateKeyByteSize = 16; -constexpr inline int kPublicKeyByteSize = 64; +inline constexpr int kPrivateKeyByteSize = 16; +inline constexpr int kPublicKeyByteSize = 64; namespace ash { namespace quick_pair {
diff --git a/ash/quick_pair/feature_status_tracker/BUILD.gn b/ash/quick_pair/feature_status_tracker/BUILD.gn index 9e99884e..eda971d 100644 --- a/ash/quick_pair/feature_status_tracker/BUILD.gn +++ b/ash/quick_pair/feature_status_tracker/BUILD.gn
@@ -17,6 +17,8 @@ "fast_pair_enabled_provider.h", "fast_pair_pref_enabled_provider.cc", "fast_pair_pref_enabled_provider.h", + "fast_pair_support_utils.cc", + "fast_pair_support_utils.h", "google_api_key_availability_provider.cc", "google_api_key_availability_provider.h", "logged_in_user_enabled_provider.cc", @@ -81,6 +83,7 @@ "base_enabled_provider_unittest.cc", "bluetooth_enabled_provider_unittest.cc", "fast_pair_enabled_provider_unittest.cc", + "fast_pair_support_utils_unittest.cc", "logged_in_user_enabled_provider_unittest.cc", "screen_state_enabled_provider_unittest.cc", ]
diff --git a/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider.cc b/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider.cc index ec51ab5a..e5481554 100644 --- a/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider.cc +++ b/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider.cc
@@ -4,7 +4,7 @@ #include "ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider.h" -#include "ash/constants/ash_features.h" +#include "ash/quick_pair/feature_status_tracker/fast_pair_support_utils.h" #include "base/bind.h" #include "base/memory/scoped_refptr.h" #include "device/bluetooth/bluetooth_adapter.h" @@ -49,7 +49,7 @@ } void BluetoothEnabledProvider::Update() { - if (!HasHardwareSupport()) { + if (!HasHardwareSupport(adapter_)) { SetEnabledAndInvokeCallback(/*is_enabled=*/false); return; } @@ -57,17 +57,5 @@ SetEnabledAndInvokeCallback(adapter_->IsPowered()); } -bool BluetoothEnabledProvider::HasHardwareSupport() { - if (!adapter_ || !adapter_->IsPresent()) - return false; - - if (features::IsFastPairSoftwareScanningEnabled()) - return true; - - return adapter_->GetLowEnergyScanSessionHardwareOffloadingStatus() == - device::BluetoothAdapter:: - LowEnergyScanSessionHardwareOffloadingStatus::kSupported; -} - } // namespace quick_pair } // namespace ash
diff --git a/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider.h b/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider.h index a8d58337..edeafb5 100644 --- a/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider.h +++ b/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider.h
@@ -35,7 +35,6 @@ void OnAdapterReceived(scoped_refptr<device::BluetoothAdapter> adapter); void Update(); - bool HasHardwareSupport(); base::ScopedObservation<device::BluetoothAdapter, device::BluetoothAdapter::Observer>
diff --git a/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider_unittest.cc b/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider_unittest.cc index 193f86c..e33730e 100644 --- a/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider_unittest.cc +++ b/ash/quick_pair/feature_status_tracker/bluetooth_enabled_provider_unittest.cc
@@ -82,6 +82,16 @@ EXPECT_FALSE(provider_->is_enabled()); } +TEST_F(BluetoothEnabledProviderTest, HasHardwareSupport) { + adapter().SetHardwareOffloadingStatus( + device::BluetoothAdapter::LowEnergyScanSessionHardwareOffloadingStatus:: + kSupported); + EXPECT_FALSE(provider_->is_enabled()); + + adapter().SetBluetoothIsPowered(true); + EXPECT_TRUE(provider_->is_enabled()); +} + TEST_F(BluetoothEnabledProviderTest, HardwareSupportBecomesAvailable) { adapter().SetHardwareOffloadingStatus( device::BluetoothAdapter::LowEnergyScanSessionHardwareOffloadingStatus::
diff --git a/ash/quick_pair/feature_status_tracker/fast_pair_support_utils.cc b/ash/quick_pair/feature_status_tracker/fast_pair_support_utils.cc new file mode 100644 index 0000000..ee98fde --- /dev/null +++ b/ash/quick_pair/feature_status_tracker/fast_pair_support_utils.cc
@@ -0,0 +1,27 @@ +// Copyright 2022 The Chromium 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/quick_pair/feature_status_tracker/fast_pair_support_utils.h" + +#include "ash/constants/ash_features.h" +#include "base/bind.h" +#include "device/bluetooth/bluetooth_adapter.h" + +namespace ash { +namespace quick_pair { + +bool HasHardwareSupport(scoped_refptr<device::BluetoothAdapter> adapter) { + if (!adapter || !adapter->IsPresent()) + return false; + + if (features::IsFastPairSoftwareScanningEnabled()) + return true; + + return adapter->GetLowEnergyScanSessionHardwareOffloadingStatus() == + device::BluetoothAdapter:: + LowEnergyScanSessionHardwareOffloadingStatus::kSupported; +} + +} // namespace quick_pair +} // namespace ash
diff --git a/ash/quick_pair/feature_status_tracker/fast_pair_support_utils.h b/ash/quick_pair/feature_status_tracker/fast_pair_support_utils.h new file mode 100644 index 0000000..ce183b4d --- /dev/null +++ b/ash/quick_pair/feature_status_tracker/fast_pair_support_utils.h
@@ -0,0 +1,21 @@ +// Copyright 2022 The Chromium 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_QUICK_PAIR_FEATURE_STATUS_TRACKER_FAST_PAIR_SUPPORT_UTILS_H_ +#define ASH_QUICK_PAIR_FEATURE_STATUS_TRACKER_FAST_PAIR_SUPPORT_UTILS_H_ + +#include "base/memory/scoped_refptr.h" +#include "device/bluetooth/bluetooth_adapter.h" + +namespace ash { +namespace quick_pair { + +// Returns true if the device has support for hardware advertisement +// filtering which is required for fast pair. +bool HasHardwareSupport(scoped_refptr<device::BluetoothAdapter> adapter); + +} // namespace quick_pair +} // namespace ash + +#endif // ASH_QUICK_PAIR_FEATURE_STATUS_TRACKER_FAST_PAIR_SUPPORT_UTILS_H_
diff --git a/ash/quick_pair/feature_status_tracker/fast_pair_support_utils_unittest.cc b/ash/quick_pair/feature_status_tracker/fast_pair_support_utils_unittest.cc new file mode 100644 index 0000000..551692d --- /dev/null +++ b/ash/quick_pair/feature_status_tracker/fast_pair_support_utils_unittest.cc
@@ -0,0 +1,64 @@ +// Copyright 2022 The Chromium 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/quick_pair/feature_status_tracker/fast_pair_support_utils.h" + +#include "ash/constants/ash_features.h" +#include "ash/quick_pair/feature_status_tracker/fake_bluetooth_adapter.h" +#include "base/memory/scoped_refptr.h" +#include "base/test/scoped_feature_list.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace ash { +namespace quick_pair { + +class FastPairSupportUtilsTest : public testing::Test { + public: + void SetUp() override { + adapter_ = base::MakeRefCounted<FakeBluetoothAdapter>(); + } + + protected: + scoped_refptr<FakeBluetoothAdapter> adapter_; +}; + +TEST_F(FastPairSupportUtilsTest, HasHardwareSupportForHardwareState) { + EXPECT_TRUE(HasHardwareSupport(adapter_)); + + adapter_->SetHardwareOffloadingStatus( + device::BluetoothAdapter::LowEnergyScanSessionHardwareOffloadingStatus:: + kNotSupported); + EXPECT_FALSE(HasHardwareSupport(adapter_)); + + adapter_->SetHardwareOffloadingStatus( + device::BluetoothAdapter::LowEnergyScanSessionHardwareOffloadingStatus:: + kSupported); + EXPECT_TRUE(HasHardwareSupport(adapter_)); +} + +TEST_F(FastPairSupportUtilsTest, HasHardwareSupportForFlagState) { + EXPECT_TRUE(HasHardwareSupport(adapter_)); + + adapter_->SetHardwareOffloadingStatus( + device::BluetoothAdapter::LowEnergyScanSessionHardwareOffloadingStatus:: + kNotSupported); + EXPECT_FALSE(HasHardwareSupport(adapter_)); + + base::test::ScopedFeatureList feature_list{ + features::kFastPairSoftwareScanning}; + EXPECT_TRUE(HasHardwareSupport(adapter_)); +} + +TEST_F(FastPairSupportUtilsTest, HasHardwareSupportFalseForAdapterState) { + EXPECT_TRUE(HasHardwareSupport(adapter_)); + + adapter_->SetBluetoothIsPresent(false); + EXPECT_FALSE(HasHardwareSupport(adapter_)); + + scoped_refptr<FakeBluetoothAdapter> null_adapter; + EXPECT_FALSE(HasHardwareSupport(null_adapter)); +} + +} // namespace quick_pair +} // namespace ash
diff --git a/ash/services/ime/decoder/system_engine_unittest.cc b/ash/services/ime/decoder/system_engine_unittest.cc index 03f5090c..100d04f 100644 --- a/ash/services/ime/decoder/system_engine_unittest.cc +++ b/ash/services/ime/decoder/system_engine_unittest.cc
@@ -79,16 +79,23 @@ ImeDecoder::EntryPoints CreateDecoderEntryPoints(TestDecoderState* state) { g_test_decoder_state = state; - ImeDecoder::EntryPoints entry_points; - entry_points.init_once = [](ImeCrosPlatform* platform) {}; - entry_points.connect_to_input_method = [](const char* ime_spec, - uint32_t receiver_pipe_handle, - uint32_t host_pipe_handle, - uint32_t host_pipe_version) { - return g_test_decoder_state->ConnectToInputMethod( - ime_spec, receiver_pipe_handle, host_pipe_handle, host_pipe_version); + ImeDecoder::EntryPoints entry_points = { + .init_once = [](ImeCrosPlatform* platform) {}, + .close = []() {}, + .supports = [](const char* ime_spec) { return true; }, + .activate_ime = [](const char* ime_spec, + ImeClientDelegate* delegate) { return true; }, + .process = [](const uint8_t* data, size_t size) {}, + .connect_to_input_method = + [](const char* ime_spec, uint32_t receiver_pipe_handle, + uint32_t host_pipe_handle, uint32_t host_pipe_version) { + return g_test_decoder_state->ConnectToInputMethod( + ime_spec, receiver_pipe_handle, host_pipe_handle, + host_pipe_version); + }, + .is_input_method_connected = []() { return false; }, }; - entry_points.is_input_method_connected = []() { return false; }; + return entry_points; }
diff --git a/ash/services/ime/ime_decoder.cc b/ash/services/ime/ime_decoder.cc index 21b067f..0a6d4b8 100644 --- a/ash/services/ime/ime_decoder.cc +++ b/ash/services/ime/ime_decoder.cc
@@ -69,26 +69,25 @@ return; } - EntryPoints entry_points; - entry_points.init_once = reinterpret_cast<ImeDecoderInitOnceFn>( - library.GetFunctionPointer(kImeDecoderInitOnceFnName)); - entry_points.supports = reinterpret_cast<ImeDecoderSupportsFn>( - library.GetFunctionPointer(kImeDecoderSupportsFnName)); - entry_points.activate_ime = reinterpret_cast<ImeDecoderActivateImeFn>( - library.GetFunctionPointer(kImeDecoderActivateImeFnName)); - entry_points.process = reinterpret_cast<ImeDecoderProcessFn>( - library.GetFunctionPointer(kImeDecoderProcessFnName)); - entry_points.close = reinterpret_cast<ImeDecoderCloseFn>( - library.GetFunctionPointer(kImeDecoderCloseFnName)); - entry_points.connect_to_input_method = - reinterpret_cast<ConnectToInputMethodFn>( - library.GetFunctionPointer(kConnectToInputMethodFnName)); - entry_points.initialize_connection_factory = - reinterpret_cast<InitializeConnectionFactoryFn>( - library.GetFunctionPointer(kInitializeConnectionFactoryFnName)); - entry_points.is_input_method_connected = - reinterpret_cast<IsInputMethodConnectedFn>( - library.GetFunctionPointer(kIsInputMethodConnectedFnName)); + EntryPoints entry_points = { + .init_once = reinterpret_cast<ImeDecoderInitOnceFn>( + library.GetFunctionPointer(kImeDecoderInitOnceFnName)), + .close = reinterpret_cast<ImeDecoderCloseFn>( + library.GetFunctionPointer(kImeDecoderCloseFnName)), + .supports = reinterpret_cast<ImeDecoderSupportsFn>( + library.GetFunctionPointer(kImeDecoderSupportsFnName)), + .activate_ime = reinterpret_cast<ImeDecoderActivateImeFn>( + library.GetFunctionPointer(kImeDecoderActivateImeFnName)), + .process = reinterpret_cast<ImeDecoderProcessFn>( + library.GetFunctionPointer(kImeDecoderProcessFnName)), + .connect_to_input_method = reinterpret_cast<ConnectToInputMethodFn>( + library.GetFunctionPointer(kConnectToInputMethodFnName)), + .initialize_connection_factory = + reinterpret_cast<InitializeConnectionFactoryFn>( + library.GetFunctionPointer(kInitializeConnectionFactoryFnName)), + .is_input_method_connected = reinterpret_cast<IsInputMethodConnectedFn>( + library.GetFunctionPointer(kIsInputMethodConnectedFnName)), + }; // Checking if entry_points_ are loaded. if (!entry_points.init_once || !entry_points.supports ||
diff --git a/ash/services/ime/ime_service_unittest.cc b/ash/services/ime/ime_service_unittest.cc index 803e3ad..7c04971 100644 --- a/ash/services/ime/ime_service_unittest.cc +++ b/ash/services/ime/ime_service_unittest.cc
@@ -97,25 +97,27 @@ ImeDecoder::EntryPoints CreateDecoderEntryPoints(TestDecoderState* state) { g_test_decoder_state = state; - ImeDecoder::EntryPoints entry_points; - entry_points.init_once = [](ImeCrosPlatform* platform) {}; - entry_points.supports = [](const char* ime_spec) { - return strcmp(kInvalidImeSpec, ime_spec) != 0; + ImeDecoder::EntryPoints entry_points = { + .init_once = [](ImeCrosPlatform* platform) {}, + .close = []() {}, + .supports = + [](const char* ime_spec) { + return strcmp(kInvalidImeSpec, ime_spec) != 0; + }, + .activate_ime = [](const char* ime_spec, + ImeClientDelegate* delegate) { return true; }, + .process = [](const uint8_t* data, size_t size) {}, + .connect_to_input_method = + [](const char* ime_spec, uint32_t receiver_pipe_handle, + uint32_t host_pipe_handle, uint32_t host_pipe_version) { + return g_test_decoder_state->ConnectToInputMethod( + ime_spec, receiver_pipe_handle, host_pipe_handle, + host_pipe_version); + }, + .is_input_method_connected = + []() { return g_test_decoder_state->IsInputMethodConnected(); }, }; - entry_points.activate_ime = [](const char* ime_spec, - ImeClientDelegate* delegate) { return true; }; - entry_points.process = [](const uint8_t* data, size_t size) {}; - entry_points.connect_to_input_method = [](const char* ime_spec, - uint32_t receiver_pipe_handle, - uint32_t host_pipe_handle, - uint32_t host_pipe_version) { - return g_test_decoder_state->ConnectToInputMethod( - ime_spec, receiver_pipe_handle, host_pipe_handle, host_pipe_version); - }; - entry_points.is_input_method_connected = []() { - return g_test_decoder_state->IsInputMethodConnected(); - }; - entry_points.close = []() {}; + return entry_points; }
diff --git a/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.h b/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.h index 886dbaa..45adecf 100644 --- a/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.h +++ b/ash/services/nearby/public/mojom/nearby_connections_mojom_traits.h
@@ -6,7 +6,7 @@ #define ASH_SERVICES_NEARBY_PUBLIC_MOJOM_NEARBY_CONNECTIONS_MOJOM_TRAITS_H_ #include "ash/services/nearby/public/mojom/nearby_connections_types.mojom.h" -#include "third_party/nearby/src/cpp/platform/api/log_message.h" +#include "third_party/nearby/src/internal/platform/implementation/log_message.h" namespace mojo {
diff --git a/ash/services/quick_pair/fast_pair_data_parser.h b/ash/services/quick_pair/fast_pair_data_parser.h index d2ea683..67092dc6 100644 --- a/ash/services/quick_pair/fast_pair_data_parser.h +++ b/ash/services/quick_pair/fast_pair_data_parser.h
@@ -16,8 +16,8 @@ #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/receiver.h" -constexpr inline int kEncryptedDataByteSize = 16; -constexpr inline int kAesBlockByteSize = 16; +inline constexpr int kEncryptedDataByteSize = 16; +inline constexpr int kAesBlockByteSize = 16; namespace ash { namespace quick_pair {
diff --git a/ash/services/quick_pair/fast_pair_decryption.h b/ash/services/quick_pair/fast_pair_decryption.h index e7b43cb..4c6943a 100644 --- a/ash/services/quick_pair/fast_pair_decryption.h +++ b/ash/services/quick_pair/fast_pair_decryption.h
@@ -16,7 +16,7 @@ namespace quick_pair { namespace fast_pair_decryption { -constexpr inline int kBlockByteSize = 16; +inline constexpr int kBlockByteSize = 16; absl::optional<DecryptedResponse> ParseDecryptedResponse( const std::array<uint8_t, 16>& aes_key_bytes,
diff --git a/ash/services/quick_pair/public/cpp/decrypted_passkey.h b/ash/services/quick_pair/public/cpp/decrypted_passkey.h index ec792b8..5d0f0a7 100644 --- a/ash/services/quick_pair/public/cpp/decrypted_passkey.h +++ b/ash/services/quick_pair/public/cpp/decrypted_passkey.h
@@ -12,7 +12,7 @@ #include "ash/services/quick_pair/public/cpp/fast_pair_message_type.h" -constexpr inline int kDecryptedPasskeySaltByteSize = 12; +inline constexpr int kDecryptedPasskeySaltByteSize = 12; namespace ash { namespace quick_pair {
diff --git a/ash/services/quick_pair/public/cpp/decrypted_response.h b/ash/services/quick_pair/public/cpp/decrypted_response.h index a7636f6..e9893ae 100644 --- a/ash/services/quick_pair/public/cpp/decrypted_response.h +++ b/ash/services/quick_pair/public/cpp/decrypted_response.h
@@ -12,8 +12,8 @@ #include "ash/services/quick_pair/public/cpp/fast_pair_message_type.h" -constexpr inline int kDecryptedResponseAddressByteSize = 6; -constexpr inline int kDecryptedResponseSaltByteSize = 9; +inline constexpr int kDecryptedResponseAddressByteSize = 6; +inline constexpr int kDecryptedResponseSaltByteSize = 9; namespace ash { namespace quick_pair {
diff --git a/ash/system/geolocation/geolocation_controller.h b/ash/system/geolocation/geolocation_controller.h index 499b476..b4dc8cf 100644 --- a/ash/system/geolocation/geolocation_controller.h +++ b/ash/system/geolocation/geolocation_controller.h
@@ -103,6 +103,10 @@ bool server_error, const base::TimeDelta elapsed); + // Virtual so that it can be overridden by a fake implementation in unit tests + // that doesn't request actual geopositions. + virtual void RequestGeoposition(); + private: // Gets now time from the `clock_` or `base::Time::Now()` if `clock_` does // not exist. @@ -116,10 +120,6 @@ // changed as a result of the geoposition change. void NotifyGeopositionChange(bool possible_change_in_timezone); - // Virtual so that it can be overridden by a fake implementation in unit tests - // that doesn't request actual geopositions. - virtual void RequestGeoposition(); - // Note that the below computation is intentionally performed every time // GetSunsetTime() or GetSunriseTime() is called rather than once whenever we // receive a geoposition (which happens at least once a day). This reduces
diff --git a/ash/system/message_center/notification_grouping_controller.cc b/ash/system/message_center/notification_grouping_controller.cc index 49e7fbcf..2985f15 100644 --- a/ash/system/message_center/notification_grouping_controller.cc +++ b/ash/system/message_center/notification_grouping_controller.cc
@@ -247,7 +247,7 @@ // Create a copy with a timestamp that is older than the copied notification. // We need to set an older timestamp so that this notification will become // the parent notification for it's notifier_id. - auto child_copy = std::make_unique<Notification>( + auto copy = std::make_unique<Notification>( message_center::NotificationType::NOTIFICATION_TYPE_SIMPLE, parent_notification.id() + message_center::kIdSuffixForGroupContainerNotification, @@ -255,14 +255,12 @@ std::u16string(), parent_notification.origin_url(), parent_notification.notifier_id(), message_center::RichNotificationData(), /*delegate=*/nullptr); - child_copy->set_timestamp(parent_notification.timestamp() - - base::Milliseconds(1)); - child_copy->set_settings_button_handler( + copy->set_timestamp(parent_notification.timestamp() - base::Milliseconds(1)); + copy->set_settings_button_handler( parent_notification.rich_notification_data().settings_button_handler); - child_copy->set_delegate(parent_notification.delegate()); - child_copy->SetGroupChild(); + copy->set_delegate(parent_notification.delegate()); - return child_copy; + return copy; } void NotificationGroupingController::RemoveGroupedChild(
diff --git a/ash/system/power/peripheral_battery_tests.h b/ash/system/power/peripheral_battery_tests.h index ac9688d..cd050bcc2 100644 --- a/ash/system/power/peripheral_battery_tests.h +++ b/ash/system/power/peripheral_battery_tests.h
@@ -12,41 +12,41 @@ // Constants common to peripheral battery listener and notifier tests. // HID device. -constexpr inline char kTestBatteryPath[] = +inline constexpr char kTestBatteryPath[] = "/sys/class/power_supply/hid-AA:BB:CC:DD:EE:FF-battery"; -constexpr inline char kTestBatteryAddress[] = "aa:bb:cc:dd:ee:ff"; -constexpr inline char kTestDeviceName[] = "test device"; -constexpr inline char16_t kTestDeviceName16[] = u"test device"; +inline constexpr char kTestBatteryAddress[] = "aa:bb:cc:dd:ee:ff"; +inline constexpr char kTestDeviceName[] = "test device"; +inline constexpr char16_t kTestDeviceName16[] = u"test device"; const inline auto kTestBatteryStatusIn = power_manager:: PeripheralBatteryStatus_ChargeStatus_CHARGE_STATUS_DISCHARGING; const inline auto kTestBatteryStatusOut = ash::PeripheralBatteryListener::BatteryInfo::ChargeStatus::kDischarging; -constexpr inline char kTestBatteryId[] = "battery_bluetooth-aa:bb:cc:dd:ee:ff"; -constexpr inline char kTestBatteryNotificationId[] = +inline constexpr char kTestBatteryId[] = "battery_bluetooth-aa:bb:cc:dd:ee:ff"; +inline constexpr char kTestBatteryNotificationId[] = "battery_notification-battery_bluetooth-aa:bb:cc:dd:ee:ff"; // Charging device -constexpr inline char kTestChargerPath[] = "/sys/class/power_supply/PCHG0"; -constexpr inline char kTestChargerName[] = ""; -constexpr inline char kTestChargerId[] = "PCHG0"; -constexpr inline char kTestOtherChargerPath[] = "/sys/class/power_supply/PCHG1"; -constexpr inline char kTestOtherChargerName[] = ""; -constexpr inline char kTestOtherChargerId[] = "PCHG1"; +inline constexpr char kTestChargerPath[] = "/sys/class/power_supply/PCHG0"; +inline constexpr char kTestChargerName[] = ""; +inline constexpr char kTestChargerId[] = "PCHG0"; +inline constexpr char kTestOtherChargerPath[] = "/sys/class/power_supply/PCHG1"; +inline constexpr char kTestOtherChargerName[] = ""; +inline constexpr char kTestOtherChargerId[] = "PCHG1"; // Bluetooth devices. -constexpr inline char kBluetoothDeviceAddress1[] = "aa:bb:cc:dd:ee:ff"; -constexpr inline char kBluetoothDeviceAddress2[] = "11:22:33:44:55:66"; -constexpr inline char kBluetoothDeviceName1[] = "device_name_1"; -constexpr inline char16_t kBluetoothDeviceName116[] = u"device_name_1"; -constexpr inline char kBluetoothDeviceName2[] = "device_name_2"; -constexpr inline char16_t kBluetoothDeviceName216[] = u"device_name_2"; -constexpr inline char kBluetoothDeviceId1[] = +inline constexpr char kBluetoothDeviceAddress1[] = "aa:bb:cc:dd:ee:ff"; +inline constexpr char kBluetoothDeviceAddress2[] = "11:22:33:44:55:66"; +inline constexpr char kBluetoothDeviceName1[] = "device_name_1"; +inline constexpr char16_t kBluetoothDeviceName116[] = u"device_name_1"; +inline constexpr char kBluetoothDeviceName2[] = "device_name_2"; +inline constexpr char16_t kBluetoothDeviceName216[] = u"device_name_2"; +inline constexpr char kBluetoothDeviceId1[] = "battery_bluetooth-aa:bb:cc:dd:ee:ff"; -constexpr inline char kBluetoothDeviceNotificationId1[] = +inline constexpr char kBluetoothDeviceNotificationId1[] = "battery_notification-battery_bluetooth-aa:bb:cc:dd:ee:ff"; -constexpr inline char kBluetoothDeviceId2[] = +inline constexpr char kBluetoothDeviceId2[] = "battery_bluetooth-11:22:33:44:55:66"; -constexpr inline char kBluetoothDeviceNotificationId2[] = +inline constexpr char kBluetoothDeviceNotificationId2[] = "battery_notification-battery_bluetooth-11:22:33:44:55:66"; // Stylus devices. @@ -69,7 +69,7 @@ // A period of time greater than full garage charge, in seconds const inline int kFullGarageChargeTime = 30; -constexpr inline char kStylusChargerDeviceName[] = "garaged-stylus-charger"; +inline constexpr char kStylusChargerDeviceName[] = "garaged-stylus-charger"; // Provide pretty-printers in aid of EXPECT_CALL() diagnostics. namespace absl {
diff --git a/ash/system/scheduled_feature/scheduled_feature.cc b/ash/system/scheduled_feature/scheduled_feature.cc index 0ff37e4..ea2be5f 100644 --- a/ash/system/scheduled_feature/scheduled_feature.cc +++ b/ash/system/scheduled_feature/scheduled_feature.cc
@@ -76,21 +76,19 @@ } TimeOfDay ScheduledFeature::GetCustomStartTime() const { - if (active_user_pref_service_) { - return TimeOfDay( - active_user_pref_service_->GetInteger(prefs_path_custom_start_time_)); - } - - return TimeOfDay(kDefaultStartTimeOffsetMinutes); + return TimeOfDay(active_user_pref_service_ + ? active_user_pref_service_->GetInteger( + prefs_path_custom_start_time_) + : kDefaultStartTimeOffsetMinutes) + .SetClock(clock_); } TimeOfDay ScheduledFeature::GetCustomEndTime() const { - if (active_user_pref_service_) { - return TimeOfDay( - active_user_pref_service_->GetInteger(prefs_path_custom_end_time_)); - } - - return TimeOfDay(kDefaultEndTimeOffsetMinutes); + return TimeOfDay(active_user_pref_service_ + ? active_user_pref_service_->GetInteger( + prefs_path_custom_end_time_) + : kDefaultEndTimeOffsetMinutes) + .SetClock(clock_); } bool ScheduledFeature::IsNowWithinSunsetSunrise() const {
diff --git a/ash/system/scheduled_feature/scheduled_feature_unittest.cc b/ash/system/scheduled_feature/scheduled_feature_unittest.cc index 0c23ebf..5934338 100644 --- a/ash/system/scheduled_feature/scheduled_feature_unittest.cc +++ b/ash/system/scheduled_feature/scheduled_feature_unittest.cc
@@ -27,6 +27,7 @@ #include "base/test/scoped_feature_list.h" #include "base/test/simple_test_clock.h" #include "base/time/time.h" +#include "base/timer/mock_timer.h" #include "components/prefs/pref_service.h" #include "ui/compositor/layer.h" #include "ui/gfx/geometry/vector3d_f.h" @@ -38,6 +39,20 @@ constexpr char kUser1Email[] = "user1@featuredschedule"; constexpr char kUser2Email[] = "user2@featuredschedule"; +enum AmPm { kAM, kPM }; + +Geoposition CreateGeoposition(double latitude, + double longitude, + base::Time timestamp) { + Geoposition position; + position.latitude = latitude; + position.longitude = longitude; + position.status = Geoposition::STATUS_OK; + position.accuracy = 10; + position.timestamp = timestamp; + return position; +} + class TestScheduledFeature : public ScheduledFeature { public: TestScheduledFeature(const std::string prefs_path_enabled, @@ -55,6 +70,69 @@ const char* GetFeatureName() const override { return "TestFeature"; } }; +// An observer class to GeolocationController which updates sunset and sunrise +// time. +class GeolocationControllerObserver : public GeolocationController::Observer { + public: + GeolocationControllerObserver() = default; + + GeolocationControllerObserver(const GeolocationControllerObserver&) = delete; + GeolocationControllerObserver& operator=( + const GeolocationControllerObserver&) = delete; + + ~GeolocationControllerObserver() override = default; + + // TODO(crbug.com/1269915): Add `sunset_` and `sunrise_` and update their + // values when receiving the new position. + void OnGeopositionChanged(bool possible_change_in_timezone) override { + position_received_num_++; + possible_change_in_timezone_ = possible_change_in_timezone; + } + + int position_received_num() const { return position_received_num_; } + bool possible_change_in_timezone() const { + return possible_change_in_timezone_; + } + + private: + // The number of times a new position is received. + int position_received_num_ = 0; + bool possible_change_in_timezone_ = false; +}; + +// A fake implementation of GeolocationController that doesn't perform any +// actual geoposition requests. +class FakeGeolocationController : public GeolocationController { + public: + FakeGeolocationController(base::SimpleTestClock* test_clock, + std::unique_ptr<base::MockOneShotTimer> mock_timer) + : GeolocationController(/*url_context_getter=*/nullptr) { + SetTimerForTesting(std::move(mock_timer)); + SetClockForTesting(test_clock); + } + + FakeGeolocationController(const FakeGeolocationController&) = delete; + FakeGeolocationController& operator=(const FakeGeolocationController&) = + delete; + + ~FakeGeolocationController() override = default; + + void set_position_to_send(const Geoposition& position) { + position_to_send_ = position; + } + + protected: + // GeolocationController: + void RequestGeoposition() override { + OnGeoposition(position_to_send_, /*server_error=*/false, base::TimeDelta()); + } + + private: + // The position to send to the observer by the controller the next time + // `OnGeoposition()` is invoked. + Geoposition position_to_send_; +}; + class ScheduledFeatureTest : public NoSessionAshTestBase { public: ScheduledFeatureTest() = default; @@ -83,17 +161,25 @@ // Simulate user 1 login. SimulateNewUserFirstLogin(kUser1Email); - geolocation_controller_ = std::make_unique<GeolocationController>( - /*url_context_getter=*/nullptr); + std::unique_ptr<base::MockOneShotTimer> mock_timer = + std::make_unique<base::MockOneShotTimer>(); + mock_timer_ptr_ = mock_timer.get(); + geolocation_controller_ = std::make_unique<FakeGeolocationController>( + &test_clock_, std::move(mock_timer)); // Use user prefs of NightLight, which is an example of ScheduledFeature. feature_ = std::make_unique<TestScheduledFeature>( prefs::kNightLightEnabled, prefs::kNightLightScheduleType, prefs::kNightLightCustomStartTime, prefs::kNightLightCustomEndTime); + ASSERT_FALSE(feature_->GetEnabled()); feature_->SetClockForTesting(&test_clock_); feature_->OnActiveUserPrefServiceChanged( Shell::Get()->session_controller()->GetActivePrefService()); + + base::Time now; + EXPECT_TRUE(base::Time::FromUTCString("23 Dec 2021 12:00:00", &now)); + test_clock_.SetNow(now); } void TearDown() override { @@ -124,10 +210,28 @@ feature_->SetScheduleType(type); } + // Convenience function for constructing a TimeOfDay object for exact hours + // during the day. |hour| is between 1 and 12. + TimeOfDay MakeTimeOfDay(int hour, AmPm am_pm) { + DCHECK_GE(hour, 1); + DCHECK_LE(hour, 12); + + if (am_pm == kAM) { + hour %= 12; + } else { + if (hour != 12) + hour += 12; + hour %= 24; + } + + return TimeOfDay(hour * 60).SetClock(&test_clock_); + } + protected: std::unique_ptr<TestScheduledFeature> feature_; - std::unique_ptr<GeolocationController> geolocation_controller_; + std::unique_ptr<FakeGeolocationController> geolocation_controller_; base::SimpleTestClock test_clock_; + base::MockOneShotTimer* mock_timer_ptr_; }; // Tests that switching users retrieves the feature settings for the active @@ -163,12 +267,12 @@ // types. TEST_F(ScheduledFeatureTest, ScheduleNoneToCustomTransition) { // Now is 6:00 PM. - test_clock_.SetNow(TimeOfDay(18 * 60).ToTimeToday()); + test_clock_.SetNow(MakeTimeOfDay(6, AmPm::kPM).ToTimeToday()); SetFeatureEnabled(false); feature()->SetScheduleType(ScheduledFeature::ScheduleType::kNone); // Start time is at 3:00 PM and end time is at 8:00 PM. - feature()->SetCustomStartTime(TimeOfDay(15 * 60)); - feature()->SetCustomEndTime(TimeOfDay(20 * 60)); + feature()->SetCustomStartTime(MakeTimeOfDay(3, AmPm::kPM)); + feature()->SetCustomEndTime(MakeTimeOfDay(8, AmPm::kPM)); // 15:00 18:00 20:00 // <----- + ----------- + ----------- + -----> @@ -197,9 +301,9 @@ // Tests what happens when the time now reaches the end of the feature // interval when the feature mode is on. TEST_F(ScheduledFeatureTest, TestCustomScheduleReachingEndTime) { - test_clock_.SetNow(TimeOfDay(18 * 60).ToTimeToday()); - feature()->SetCustomStartTime(TimeOfDay(15 * 60)); - feature()->SetCustomEndTime(TimeOfDay(20 * 60)); + test_clock_.SetNow(MakeTimeOfDay(6, AmPm::kPM).ToTimeToday()); + feature()->SetCustomStartTime(MakeTimeOfDay(3, AmPm::kPM)); + feature()->SetCustomEndTime(MakeTimeOfDay(8, AmPm::kPM)); feature()->SetScheduleType(ScheduledFeature::ScheduleType::kCustom); EXPECT_TRUE(GetEnabled()); @@ -212,7 +316,7 @@ // start end & now // // Now is 8:00 PM. - test_clock_.SetNow(TimeOfDay(20 * 60).ToTimeToday()); + test_clock_.SetNow(MakeTimeOfDay(8, AmPm::kPM).ToTimeToday()); feature()->timer()->FireNow(); EXPECT_FALSE(GetEnabled()); // The timer should still be running, but now scheduling the start at 3:00 PM @@ -231,9 +335,9 @@ // | | | // start end now // - test_clock_.SetNow(TimeOfDay(23 * 60).ToTimeToday()); - feature()->SetCustomStartTime(TimeOfDay(15 * 60)); - feature()->SetCustomEndTime(TimeOfDay(20 * 60)); + test_clock_.SetNow(MakeTimeOfDay(11, AmPm::kPM).ToTimeToday()); + feature()->SetCustomStartTime(MakeTimeOfDay(3, AmPm::kPM)); + feature()->SetCustomEndTime(MakeTimeOfDay(8, AmPm::kPM)); feature()->SetScheduleType(ScheduledFeature::ScheduleType::kCustom); EXPECT_FALSE(GetEnabled()); @@ -266,11 +370,11 @@ // | | | // now start end // - test_clock_.SetNow(TimeOfDay(16 * 60).ToTimeToday()); // 4:00 PM. + test_clock_.SetNow(MakeTimeOfDay(4, AmPm::kPM).ToTimeToday()); // 4:00 PM. SetFeatureEnabled(false); feature()->SetScheduleType(ScheduledFeature::ScheduleType::kNone); - feature()->SetCustomStartTime(TimeOfDay(18 * 60)); // 6:00 PM. - feature()->SetCustomEndTime(TimeOfDay(22 * 60)); // 10:00 PM. + feature()->SetCustomStartTime(MakeTimeOfDay(6, AmPm::kPM)); // 6:00 PM. + feature()->SetCustomEndTime(MakeTimeOfDay(10, AmPm::kPM)); // 10:00 PM. // Since now is outside the feature interval, changing the schedule type // to kCustom, shouldn't affect the status. Validate the timer is running @@ -282,14 +386,14 @@ // Change the start time in such a way that doesn't change the status, but // despite that, confirm that schedule has been updated. - feature()->SetCustomStartTime(TimeOfDay(19 * 60)); // 7:00 PM. + feature()->SetCustomStartTime(MakeTimeOfDay(7, AmPm::kPM)); // 7:00 PM. EXPECT_FALSE(GetEnabled()); EXPECT_TRUE(feature()->timer()->IsRunning()); EXPECT_EQ(base::Hours(3), feature()->timer()->GetCurrentDelay()); // Changing the end time in a similar fashion to the above and expect no // change. - feature()->SetCustomEndTime(TimeOfDay(23 * 60)); // 11:00 PM. + feature()->SetCustomEndTime(MakeTimeOfDay(11, AmPm::kPM)); // 11:00 PM. EXPECT_FALSE(GetEnabled()); EXPECT_TRUE(feature()->timer()->IsRunning()); EXPECT_EQ(base::Hours(3), feature()->timer()->GetCurrentDelay()); @@ -301,7 +405,7 @@ EXPECT_FALSE(GetEnabled()); // Set time now to 10:00 AM. - base::Time current_time = TimeOfDay(10 * 60).ToTimeToday(); + base::Time current_time = MakeTimeOfDay(10, AmPm::kAM).ToTimeToday(); test_clock_.SetNow(current_time); EXPECT_FALSE(feature()->timer()->IsRunning()); feature()->SetScheduleType(ScheduledFeature::ScheduleType::kSunsetToSunrise); @@ -317,9 +421,9 @@ feature()->timer()->FireNow(); EXPECT_TRUE(feature()->timer()->IsRunning()); EXPECT_TRUE(GetEnabled()); - EXPECT_EQ(geolocation_controller_->GetSunriseTime() + base::Hours(24) - - current_time, - feature()->timer()->GetCurrentDelay()); + EXPECT_EQ( + geolocation_controller_->GetSunriseTime() + base::Days(1) - current_time, + feature()->timer()->GetCurrentDelay()); // Firing a timer should advance the time to sunrise and automatically turn // off the feature. @@ -332,6 +436,137 @@ feature()->timer()->GetCurrentDelay()); } +// Tests that scheduled start time and end time of sunset-to-sunrise feature +// are updated correctly if the geoposition changes. +TEST_F(ScheduledFeatureTest, SunsetSunriseGeoposition) { + constexpr double kFakePosition1_Latitude = 23.5; + constexpr double kFakePosition1_Longitude = 55.88; + constexpr double kFakePosition2_Latitude = 23.5; + constexpr double kFakePosition2_Longitude = 10.9; + // Position 1 sunset and sunrise times. + // + // sunset-4 + // <----- + --------- + ---------------- + -------> + // | | | + // now sunset sunrise + // + + // Prepare a valid geoposition. + const Geoposition position = CreateGeoposition( + kFakePosition1_Latitude, kFakePosition1_Longitude, test_clock_.Now()); + + GeolocationControllerObserver observer1; + geolocation_controller_->AddObserver(&observer1); + EXPECT_TRUE(mock_timer_ptr_->IsRunning()); + geolocation_controller_->set_position_to_send(position); + EXPECT_FALSE(observer1.possible_change_in_timezone()); + + // Fire timer to fetch position update. + mock_timer_ptr_->Fire(); + EXPECT_TRUE(observer1.possible_change_in_timezone()); + const base::Time sunset_time1 = geolocation_controller_->GetSunsetTime(); + const base::Time sunrise_time1 = geolocation_controller_->GetSunriseTime(); + // Our assumption is that GeolocationController gives us sunrise time + // earlier in the same day before sunset. + ASSERT_GT(sunset_time1, sunrise_time1); + ASSERT_LT(sunset_time1 - base::Days(1), sunrise_time1); + + // Set time now to be 4 hours before sunset. + test_clock_.SetNow(sunset_time1 - base::Hours(4)); + + // Expect that timer is running and the start is scheduled after 4 hours. + EXPECT_FALSE(feature()->GetEnabled()); + feature()->SetScheduleType(ScheduledFeature::ScheduleType::kSunsetToSunrise); + EXPECT_FALSE(feature()->GetEnabled()); + EXPECT_TRUE(feature()->timer()->IsRunning()); + EXPECT_EQ(base::Hours(4), feature()->timer()->GetCurrentDelay()); + + // Simulate reaching sunset. + test_clock_.SetNow(sunset_time1); // Now is sunset time of the position1. + feature()->timer()->FireNow(); + EXPECT_TRUE(feature()->GetEnabled()); + // Timer is running scheduling the end at sunrise of the second day. + EXPECT_TRUE(feature()->timer()->IsRunning()); + EXPECT_EQ(sunrise_time1 + base::Days(1) - test_clock_.Now(), + feature()->timer()->GetCurrentDelay()); + + // Simulate reaching sunrise. + test_clock_.SetNow(sunrise_time1); // Now is sunrise time of the position1 + + // Now simulate user changing position. + // Position 2 sunset and sunrise times. + // + // <----- + --------- + ---------------- + -------> + // | | | + // sunset2 now (sunrise1) sunrise2 + // + + const Geoposition position2 = CreateGeoposition( + kFakePosition2_Latitude, kFakePosition2_Longitude, test_clock_.Now()); + geolocation_controller_->set_position_to_send(position2); + mock_timer_ptr_->Fire(); + EXPECT_TRUE(observer1.possible_change_in_timezone()); + const base::Time sunset_time2 = geolocation_controller_->GetSunsetTime(); + const base::Time sunrise_time2 = geolocation_controller_->GetSunriseTime(); + // We choose the second location such that the new sunrise time is later + // in the day compared to the old sunrise time, which is also the current + // time. + ASSERT_GT(test_clock_.Now(), sunset_time2); + ASSERT_LT(test_clock_.Now(), sunset_time2 + base::Days(1)); + ASSERT_GT(test_clock_.Now(), sunrise_time2); + ASSERT_LT(test_clock_.Now(), sunrise_time2 + base::Days(1)); + + // Expect that the scheduled end delay has been updated to sunrise of the + // same (second) day in location 2, and the status hasn't changed. + EXPECT_TRUE(feature()->GetEnabled()); + EXPECT_TRUE(feature()->timer()->IsRunning()); + EXPECT_EQ(sunrise_time2 + base::Days(1) - test_clock_.Now(), + feature()->timer()->GetCurrentDelay()); + + // Simulate reaching sunrise. + test_clock_.SetNow(sunrise_time2 + + base::Days(1)); // Now is sunrise time of the position2. + feature()->timer()->FireNow(); + EXPECT_FALSE(feature()->GetEnabled()); + // Timer is running scheduling the start at the sunset of the next day. + EXPECT_TRUE(feature()->timer()->IsRunning()); + EXPECT_EQ(sunset_time2 + base::Days(1) - test_clock_.Now(), + feature()->timer()->GetCurrentDelay()); +} + +// Tests that on device resume from sleep, the feature status is updated +// correctly if the time has changed meanwhile. +TEST_F(ScheduledFeatureTest, CustomScheduleOnResume) { + // Now is 4:00 PM. + test_clock_.SetNow(MakeTimeOfDay(4, AmPm::kPM).ToTimeToday()); + feature()->SetEnabled(false); + // Start time is at 6:00 PM and end time is at 10:00 PM. The feature should be + // off. + // 16:00 18:00 22:00 + // <----- + ----------- + ----------- + -----> + // | | | + // now start end + // + feature()->SetCustomStartTime(MakeTimeOfDay(6, AmPm::kPM)); + feature()->SetCustomEndTime(MakeTimeOfDay(10, AmPm::kPM)); + feature()->SetScheduleType(ScheduledFeature::ScheduleType::kCustom); + + EXPECT_FALSE(feature()->GetEnabled()); + EXPECT_TRUE(feature()->timer()->IsRunning()); + // The feature should be enabled in 2 hours. + EXPECT_EQ(base::Hours(2), feature()->timer()->GetCurrentDelay()); + + // Now simulate that the device was suspended for 3 hours, and the time now + // is 7:00 PM when the devices was resumed. Expect that the feature turns on. + test_clock_.SetNow(MakeTimeOfDay(7, AmPm::kPM).ToTimeToday()); + feature()->SuspendDone(base::TimeDelta::Max()); + + EXPECT_TRUE(feature()->GetEnabled()); + EXPECT_TRUE(feature()->timer()->IsRunning()); + // The feature should be disabled in 3 hours. + EXPECT_EQ(base::Hours(3), feature()->timer()->GetCurrentDelay()); +} + // The following tests ensure that the feature schedule is correctly // refreshed when the start and end times are inverted (i.e. the "start time" as // a time of day today is in the future with respect to the "end time" also as a @@ -340,7 +575,7 @@ // Case 1: "Now" is less than both "end" and "start". TEST_F(ScheduledFeatureTest, CustomScheduleInvertedStartAndEndTimesCase1) { // Now is 4:00 AM. - test_clock_.SetNow(TimeOfDay(4 * 60).ToTimeToday()); + test_clock_.SetNow(MakeTimeOfDay(4, AmPm::kAM).ToTimeToday()); SetFeatureEnabled(false); // Start time is at 9:00 PM and end time is at 6:00 AM. "Now" is less than // both. The feature should be on. @@ -349,8 +584,8 @@ // | | | // now end start // - feature()->SetCustomStartTime(TimeOfDay(21 * 60)); - feature()->SetCustomEndTime(TimeOfDay(6 * 60)); + feature()->SetCustomStartTime(MakeTimeOfDay(9, AmPm::kPM)); + feature()->SetCustomEndTime(MakeTimeOfDay(6, AmPm::kAM)); feature()->SetScheduleType(ScheduledFeature::ScheduleType::kCustom); EXPECT_TRUE(GetEnabled()); @@ -362,7 +597,7 @@ // Case 2: "Now" is between "end" and "start". TEST_F(ScheduledFeatureTest, CustomScheduleInvertedStartAndEndTimesCase2) { // Now is 6:00 AM. - test_clock_.SetNow(TimeOfDay(6 * 60).ToTimeToday()); + test_clock_.SetNow(MakeTimeOfDay(6, AmPm::kAM).ToTimeToday()); SetFeatureEnabled(false); // Start time is at 9:00 PM and end time is at 4:00 AM. "Now" is between both. // The feature should be off. @@ -371,8 +606,8 @@ // | | | // end now start // - feature()->SetCustomStartTime(TimeOfDay(21 * 60)); - feature()->SetCustomEndTime(TimeOfDay(4 * 60)); + feature()->SetCustomStartTime(MakeTimeOfDay(9, AmPm::kPM)); + feature()->SetCustomEndTime(MakeTimeOfDay(4, AmPm::kAM)); feature()->SetScheduleType(ScheduledFeature::ScheduleType::kCustom); EXPECT_FALSE(GetEnabled()); @@ -384,17 +619,17 @@ // Case 3: "Now" is greater than both "start" and "end". TEST_F(ScheduledFeatureTest, CustomScheduleInvertedStartAndEndTimesCase3) { // Now is 11:00 PM. - test_clock_.SetNow(TimeOfDay(23 * 60).ToTimeToday()); + test_clock_.SetNow(MakeTimeOfDay(11, AmPm::kPM).ToTimeToday()); SetFeatureEnabled(false); // Start time is at 9:00 PM and end time is at 4:00 AM. "Now" is greater than - // both. NightLight should be on. + // both. the feature should be on. // 4:00 21:00 23:00 // <----- + ----------- + ----------- + -----> // | | | // end start now // - feature()->SetCustomStartTime(TimeOfDay(21 * 60)); - feature()->SetCustomEndTime(TimeOfDay(4 * 60)); + feature()->SetCustomStartTime(MakeTimeOfDay(9, AmPm::kPM)); + feature()->SetCustomEndTime(MakeTimeOfDay(4, AmPm::kAM)); feature()->SetScheduleType(ScheduledFeature::ScheduleType::kCustom); EXPECT_TRUE(GetEnabled()); @@ -403,6 +638,130 @@ EXPECT_EQ(base::Hours(5), feature()->timer()->GetCurrentDelay()); } +// Tests that manual changes to the feature status while a schedule is being +// used will be remembered and reapplied across user switches. +TEST_F(ScheduledFeatureTest, MultiUserManualStatusToggleWithSchedules) { + // Setup user 1 to use a custom schedule from 3pm till 8pm, and user 2 to use + // a sunset-to-sunrise schedule from 6pm till 6am. + // + // + // |<--- User 1 NL on --->| + // | | + // <--------+-------------+--------+----------------------------+-----------> + // 3pm 6pm 8pm 6am + // | | + // |<----------- User 2 NL on ---------->| + // + // Test cases at: + // + // <---+---------+------------+------------+----------------------------+---> + // 2pm 4pm 7pm 10pm 9am + // + + test_clock_.SetNow(MakeTimeOfDay(2, kPM).ToTimeToday()); + feature()->SetCustomStartTime(MakeTimeOfDay(3, kPM)); + feature()->SetCustomEndTime(MakeTimeOfDay(8, kPM)); + feature()->SetScheduleType(ScheduledFeature::ScheduleType::kCustom); + SwitchActiveUser(kUser2Email); + feature()->SetScheduleType(ScheduledFeature::ScheduleType::kSunsetToSunrise); + SwitchActiveUser(kUser1Email); + + struct { + base::Time fake_now; + bool user_1_expected_status; + bool user_2_expected_status; + } kTestCases[] = { + {MakeTimeOfDay(2, kPM).ToTimeToday(), false, false}, + {MakeTimeOfDay(4, kPM).ToTimeToday(), true, false}, + {MakeTimeOfDay(7, kPM).ToTimeToday(), true, true}, + {MakeTimeOfDay(10, kPM).ToTimeToday(), false, true}, + {MakeTimeOfDay(9, kAM).ToTimeToday() + + base::Days(1), // 9:00 AM tomorrow. + false, false}, + }; + + bool user_1_previous_status = false; + for (const auto& test_case : kTestCases) { + // Each test case begins when user_1 is active. + const bool user_1_toggled_status = !test_case.user_1_expected_status; + const bool user_2_toggled_status = !test_case.user_2_expected_status; + + // Apply the test's case fake time, and fire the timer if there's a change + // expected in the feature's status. + test_clock_.SetNow(test_case.fake_now); + if (user_1_previous_status != test_case.user_1_expected_status) + feature()->timer()->FireNow(); + user_1_previous_status = test_case.user_1_expected_status; + + // The untoggled states for both users should match the expected ones + // according to their schedules. + EXPECT_EQ(test_case.user_1_expected_status, feature()->GetEnabled()); + SwitchActiveUser(kUser2Email); + EXPECT_EQ(test_case.user_2_expected_status, feature()->GetEnabled()); + + // Manually toggle the feature for user_2 and expect that it will be + // remembered when we switch to user_1 and back. + feature()->SetEnabled(user_2_toggled_status); + EXPECT_EQ(user_2_toggled_status, feature()->GetEnabled()); + SwitchActiveUser(kUser1Email); + EXPECT_EQ(test_case.user_1_expected_status, feature()->GetEnabled()); + SwitchActiveUser(kUser2Email); + EXPECT_EQ(user_2_toggled_status, feature()->GetEnabled()); + + // Toggle it for user_1 as well, and expect it will be remembered and won't + // affect the already toggled state for user_2. + SwitchActiveUser(kUser1Email); + EXPECT_EQ(test_case.user_1_expected_status, feature()->GetEnabled()); + feature()->SetEnabled(user_1_toggled_status); + EXPECT_EQ(user_1_toggled_status, feature()->GetEnabled()); + SwitchActiveUser(kUser2Email); + EXPECT_EQ(user_2_toggled_status, feature()->GetEnabled()); + + // Toggle both users back to their original states in preparation for the + // next test case. + feature()->SetEnabled(test_case.user_2_expected_status); + EXPECT_EQ(test_case.user_2_expected_status, feature()->GetEnabled()); + SwitchActiveUser(kUser1Email); + EXPECT_EQ(user_1_toggled_status, feature()->GetEnabled()); + feature()->SetEnabled(test_case.user_1_expected_status); + EXPECT_EQ(test_case.user_1_expected_status, feature()->GetEnabled()); + } +} + +TEST_F(ScheduledFeatureTest, + ManualStatusToggleCanPersistAfterResumeFromSuspend) { + test_clock_.SetNow(MakeTimeOfDay(11, kAM).ToTimeToday()); + + feature()->SetCustomStartTime(MakeTimeOfDay(3, kPM)); + feature()->SetCustomEndTime(MakeTimeOfDay(8, kPM)); + feature()->SetScheduleType(ScheduledFeature::ScheduleType::kCustom); + EXPECT_FALSE(feature()->GetEnabled()); + + // Toggle the status manually and expect that the feature is scheduled to + // turn back off at 8:00 PM. + feature()->SetEnabled(true); + EXPECT_TRUE(feature()->GetEnabled()); + EXPECT_TRUE(feature()->timer()->IsRunning()); + EXPECT_EQ(base::Hours(9), feature()->timer()->GetCurrentDelay()); + + // Simulate suspend and then resume at 2:00 PM (which is outside the user's + // custom schedule). However, the manual toggle to on should be kept. + test_clock_.SetNow(MakeTimeOfDay(2, kPM).ToTimeToday()); + feature()->SuspendDone(base::TimeDelta{}); + EXPECT_TRUE(feature()->GetEnabled()); + + // Suspend again and resume at 5:00 PM (which is within the user's custom + // schedule). The schedule should be applied normally. + test_clock_.SetNow(MakeTimeOfDay(5, kPM).ToTimeToday()); + feature()->SuspendDone(base::TimeDelta{}); + EXPECT_TRUE(feature()->GetEnabled()); + + // Suspend and resume at 9:00 PM and expect the feature to be off. + test_clock_.SetNow(MakeTimeOfDay(9, kPM).ToTimeToday()); + feature()->SuspendDone(base::TimeDelta{}); + EXPECT_FALSE(feature()->GetEnabled()); +} + } // namespace } // namespace ash \ No newline at end of file
diff --git a/ash/system/time/calendar_view.cc b/ash/system/time/calendar_view.cc index 64e2933..e8dcbde4 100644 --- a/ash/system/time/calendar_view.cc +++ b/ash/system/time/calendar_view.cc
@@ -12,6 +12,7 @@ #include "ash/system/time/calendar_metrics.h" #include "ash/system/time/calendar_month_view.h" #include "ash/system/time/calendar_utils.h" +#include "ash/system/time/calendar_view_controller.h" #include "ash/system/tray/tray_popup_utils.h" #include "ash/system/tray/tri_view.h" #include "base/bind.h" @@ -25,6 +26,7 @@ #include "ui/compositor/layer.h" #include "ui/gfx/animation/tween.h" #include "ui/gfx/geometry/point.h" +#include "ui/gfx/geometry/transform.h" #include "ui/gfx/interpolated_transform.h" #include "ui/views/accessibility/view_accessibility.h" #include "ui/views/animation/animation_builder.h" @@ -66,6 +68,10 @@ constexpr base::TimeDelta kAnimationDurationForEventsMoving = base::Milliseconds(400); +// Duration of closing events panel animation. +constexpr base::TimeDelta kAnimationDurationForClosingEvents = + base::Milliseconds(200); + // The cool-down time for enabling animation. constexpr base::TimeDelta kAnimationDisablingTimeout = base::Milliseconds(500); @@ -226,6 +232,21 @@ header_year_->SetText(year); } +CalendarEventListContainer::CalendarEventListContainer( + CalendarViewController* controller) + : event_list_( + AddChildView(std::make_unique<CalendarEventListView>(controller))) { + SetLayoutManager(std::make_unique<views::BoxLayout>( + views::BoxLayout::Orientation::kVertical)); + GetViewAccessibility().OverrideName(GetClassName()); + + event_list_->GetViewAccessibility().OverrideName(GetClassName()); + event_list_->GetViewAccessibility().OverrideRole(ax::mojom::Role::kGroup); + event_list_->SetFocusBehavior(FocusBehavior::ALWAYS); +} + +CalendarEventListContainer::~CalendarEventListContainer() = default; + CalendarView::CalendarView(DetailedViewDelegate* delegate, UnifiedSystemTrayController* controller) : TrayDetailedView(delegate), @@ -651,8 +672,7 @@ gfx::Vector2dF moving_location = gfx::Vector2dF( 0, calendar_view_controller_->was_on_later_month() ? -header_height / 2 : header_height / 2); - gfx::Transform initial_state = gfx::TransformAboutPivot( - header_->GetLocalBounds().CenterPoint(), gfx::Transform()); + gfx::Transform initial_state; initial_state.Translate(moving_location); set_should_header_animate(false); @@ -716,20 +736,13 @@ // The event list is in a container, which will be used for escaping the // focusing from the date cells. - event_list_container_ = AddChildView(std::make_unique<views::View>()); - event_list_container_->SetLayoutManager(std::make_unique<views::BoxLayout>( - views::BoxLayout::Orientation::kVertical)); - event_list_container_->GetViewAccessibility().OverrideName(GetClassName()); + event_list_container_ = + AddChildView(std::make_unique<CalendarEventListContainer>( + calendar_view_controller_.get())); event_list_container_->SetFocusBehavior( IsDateCellViewFocused() ? FocusBehavior::ALWAYS : FocusBehavior::NEVER); - event_list_ = event_list_container_->AddChildView( - std::make_unique<CalendarEventListView>(calendar_view_controller_.get())); - event_list_->GetViewAccessibility().OverrideName(GetClassName()); - event_list_->GetViewAccessibility().OverrideRole(ax::mojom::Role::kGroup); - event_list_->SetFocusBehavior(FocusBehavior::ALWAYS); - - event_list_->SetBounds( + event_list_container_->event_list()->SetBounds( scroll_view_->GetVisibleRect().x(), scroll_view_->GetVisibleRect().bottom(), scroll_view_->GetVisibleRect().width(), @@ -744,26 +757,12 @@ gfx::Vector2dF moving_up_location = gfx::Vector2dF( 0, -PositionOfSelectedDate() + scroll_view_->GetVisibleRect().y()); - gfx::Transform current_month_moving = gfx::TransformAboutPivot( - current_month_->GetLocalBounds().CenterPoint(), gfx::Transform()); - current_month_moving.Translate(moving_up_location); + gfx::Transform month_moving; + month_moving.Translate(moving_up_location); - gfx::Transform current_label_moving = gfx::TransformAboutPivot( - current_label_->GetLocalBounds().CenterPoint(), gfx::Transform()); - current_label_moving.Translate(moving_up_location); - - gfx::Transform next_label_moving = gfx::TransformAboutPivot( - next_label_->GetLocalBounds().CenterPoint(), gfx::Transform()); - next_label_moving.Translate(moving_up_location); - - gfx::Transform next_month_moving = gfx::TransformAboutPivot( - next_month_->GetLocalBounds().CenterPoint(), gfx::Transform()); - next_month_moving.Translate(moving_up_location); - - gfx::Transform list_view_moving = gfx::TransformAboutPivot( - event_list_->GetBoundsInScreen().CenterPoint(), gfx::Transform()); + gfx::Transform list_view_moving; list_view_moving.Translate(gfx::Vector2dF( - 0, -event_list_->GetBoundsInScreen().y() + + 0, -event_list_container_->event_list()->GetBoundsInScreen().y() + scroll_view_->GetBoundsInScreen().bottom() - calendar_view_controller_->expanded_area_available_height())); @@ -785,18 +784,15 @@ }, weak_factory_.GetWeakPtr())) .Once() - .SetTransform(current_month_, std::move(current_month_moving), - gfx::Tween::EASE_OUT_2) - .SetTransform(current_label_, std::move(current_label_moving), - gfx::Tween::EASE_OUT_2) - .SetTransform(next_label_, std::move(next_label_moving), - gfx::Tween::EASE_OUT_2) - .SetTransform(next_month_, std::move(next_month_moving), - gfx::Tween::EASE_OUT_2) + .SetDuration(calendar_utils::kAnimationDurationForMoving) + .SetTransform(current_month_, month_moving, gfx::Tween::EASE_OUT_2) + .SetTransform(current_label_, month_moving, gfx::Tween::EASE_OUT_2) + .SetTransform(next_label_, month_moving, gfx::Tween::EASE_OUT_2) + .SetTransform(next_month_, month_moving, gfx::Tween::EASE_OUT_2) .At(base::Milliseconds(0)) .SetDuration(kAnimationDurationForEventsMoving) - .SetTransform(event_list_, std::move(list_view_moving), - gfx::Tween::EASE_OUT_2); + .SetTransform(event_list_container_->event_list(), + std::move(list_view_moving), gfx::Tween::EASE_OUT_2); } void CalendarView::CloseEventList() { @@ -810,10 +806,46 @@ scroll_view_->ClipHeightTo(0, INT_MAX); scroll_view_->SetVerticalScrollBarMode( views::ScrollView::ScrollBarMode::kHiddenButEnabled); - RemoveChildViewT(event_list_container_); - event_list_container_ = nullptr; - event_list_ = nullptr; - calendar_view_controller_->OnEventListClosed(); + + // The position of the `event_list_container_->event_list()` is on the most + // top the calendar view after the height of the `scroll_view_` is set to max. + // This init set it to the correct position. + const int init_position = + event_list_container_->GetBoundsInScreen().y() - GetBoundsInScreen().y(); + gfx::Transform list_view_moving_init; + list_view_moving_init.Translate(0, init_position); + + // Then based on the `event_list_container_->event_list()`'s position, move it + // out of the visible view. + gfx::Transform list_view_moving; + list_view_moving.Translate(gfx::Vector2dF( + 0, calendar_view_controller_->expanded_area_available_height() + + init_position)); + + views::AnimationBuilder() + .SetPreemptionStrategy( + ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET) + .OnEnded(base::BindOnce( + [](base::WeakPtr<CalendarView> calendar_view) { + if (!calendar_view) + return; + calendar_view->OnCloseEventListAnimationComplete(); + }, + weak_factory_.GetWeakPtr())) + .OnAborted(base::BindOnce( + [](base::WeakPtr<CalendarView> calendar_view) { + if (!calendar_view) + return; + calendar_view->OnCloseEventListAnimationComplete(); + }, + weak_factory_.GetWeakPtr())) + .Once() + .SetTransform(event_list_container_->event_list(), + std::move(list_view_moving_init)) + .Then() + .SetDuration(kAnimationDurationForClosingEvents) + .SetTransform(event_list_container_->event_list(), + std::move(list_view_moving), gfx::Tween::FAST_OUT_SLOW_IN); } void CalendarView::ScrollUpOneMonth() { @@ -934,34 +966,16 @@ 0, -current_month_->GetPreferredSize().height() - next_label_->GetPreferredSize().height() + (scroll_view_->GetVisibleRect().y() - current_month_->y())); - gfx::Vector2dF moving_location = - is_scrolling_up ? moving_up_location : moving_down_location; - gfx::Transform current_month_moving = gfx::TransformAboutPivot( - current_month_->GetLocalBounds().CenterPoint(), gfx::Transform()); - current_month_moving.Translate(moving_location); - gfx::Transform current_label_moving = gfx::TransformAboutPivot( - current_label_->GetLocalBounds().CenterPoint(), gfx::Transform()); - current_label_moving.Translate(moving_location); - gfx::Transform previous_month_moving = gfx::TransformAboutPivot( - previous_month_->GetLocalBounds().CenterPoint(), gfx::Transform()); - previous_month_moving.Translate(moving_location); - gfx::Transform previous_label_moving = gfx::TransformAboutPivot( - previous_label_->GetLocalBounds().CenterPoint(), gfx::Transform()); - previous_label_moving.Translate(moving_location); - gfx::Transform next_label_moving = gfx::TransformAboutPivot( - next_label_->GetLocalBounds().CenterPoint(), gfx::Transform()); - next_label_moving.Translate(moving_location); - gfx::Transform next_month_moving = gfx::TransformAboutPivot( - next_month_->GetLocalBounds().CenterPoint(), gfx::Transform()); - next_month_moving.Translate(moving_location); + gfx::Transform month_moving; + month_moving.Translate(is_scrolling_up ? moving_up_location + : moving_down_location); const int header_height = header_->GetPreferredSize().height(); const gfx::Vector2dF header_moving_location = gfx::Vector2dF( 0, calendar_view_controller_->was_on_later_month() ? header_height / 2 : -header_height / 2); - gfx::Transform header_moving = gfx::TransformAboutPivot( - header_->GetLocalBounds().CenterPoint(), gfx::Transform()); + gfx::Transform header_moving; header_moving.Translate(header_moving_location); views::AnimationBuilder() @@ -986,18 +1000,12 @@ weak_factory_.GetWeakPtr(), is_scrolling_up)) .Once() .SetDuration(calendar_utils::kAnimationDurationForMoving * 2) - .SetTransform(current_month_, std::move(current_month_moving), - gfx::Tween::EASE_OUT_2) - .SetTransform(current_label_, std::move(current_label_moving), - gfx::Tween::EASE_OUT_2) - .SetTransform(previous_month_, std::move(previous_month_moving), - gfx::Tween::EASE_OUT_2) - .SetTransform(previous_label_, std::move(previous_label_moving), - gfx::Tween::EASE_OUT_2) - .SetTransform(next_month_, std::move(next_month_moving), - gfx::Tween::EASE_OUT_2) - .SetTransform(next_label_, std::move(next_label_moving), - gfx::Tween::EASE_OUT_2) + .SetTransform(current_month_, month_moving, gfx::Tween::EASE_OUT_2) + .SetTransform(current_label_, month_moving, gfx::Tween::EASE_OUT_2) + .SetTransform(previous_month_, month_moving, gfx::Tween::EASE_OUT_2) + .SetTransform(previous_label_, month_moving, gfx::Tween::EASE_OUT_2) + .SetTransform(next_month_, month_moving, gfx::Tween::EASE_OUT_2) + .SetTransform(next_label_, month_moving, gfx::Tween::EASE_OUT_2) .At(calendar_utils::kAnimationDurationForMoving) .SetDuration(calendar_utils::kAnimationDurationForMoving) .SetTransform(header_, std::move(header_moving), gfx::Tween::EASE_OUT_2) @@ -1071,8 +1079,8 @@ // goes to the next focusable button in the header. if (key_event->type() == ui::EventType::ET_KEY_PRESSED && views::FocusManager::IsTabTraversalKeyEvent(*key_event)) { - // Set focus on `scroll_view_`/`event_list_` or null pointer to escape the - // focusing on the date cell. + // Set focus on `scroll_view_`/`event_list_container_->event_list()` or null + // pointer to escape the focusing on the date cell. if (key_event->IsShiftDown()) { scroll_view_->RequestFocus(); } else if (event_list_container_) { @@ -1256,7 +1264,7 @@ PositionOfSelectedDate()); scroll_view_->ClipHeightTo(0, kExpandedCalendarViewHeightScale * calendar_view_controller_->row_height()); - event_list_->SetTransform(gfx::Transform()); + event_list_container_->event_list()->SetTransform(gfx::Transform()); if (!should_months_animate_) months_animation_restart_timer_.Reset(); scroll_view_->SetVerticalScrollBarMode( @@ -1274,6 +1282,12 @@ } } +void CalendarView::OnCloseEventListAnimationComplete() { + RemoveChildViewT(event_list_container_); + event_list_container_ = nullptr; + calendar_view_controller_->OnEventListClosed(); +} + BEGIN_METADATA(CalendarView, views::View) END_METADATA
diff --git a/ash/system/time/calendar_view.h b/ash/system/time/calendar_view.h index b1739aa7..1eea9fd 100644 --- a/ash/system/time/calendar_view.h +++ b/ash/system/time/calendar_view.h
@@ -60,6 +60,21 @@ views::Label* const header_year_; }; +// The container for a `CalendarEventListView`. +class CalendarEventListContainer : public views::View { + public: + explicit CalendarEventListContainer(CalendarViewController* controller); + CalendarEventListContainer(const CalendarEventListContainer& other) = delete; + CalendarEventListContainer& operator=( + const CalendarEventListContainer& other) = delete; + ~CalendarEventListContainer() override; + + CalendarEventListView* event_list() { return event_list_; } + + private: + CalendarEventListView* const event_list_; +}; + // This view displays a scrollable calendar. class ASH_EXPORT CalendarView : public CalendarViewController::Observer, public TrayDetailedView, @@ -188,10 +203,12 @@ // Adjusts the Chrome Vox box position for date cells in the scroll view. void AdjustDateCellVoxBounds(); - // Handles the position and status of `event_list_` and other views after the - // opening event list animation. Such as restoring the position of them, - // re-enabling animation and etc. + // Handles the position and status of `event_list_container_->event_list()` + // and other views after the opening event list animation or closing event + // list animation. Such as restoring the position of them, re-enabling + // animation and etc. void OnOpenEventListAnimationComplete(); + void OnCloseEventListAnimationComplete(); // Unowned. UnifiedSystemTrayController* controller_; @@ -226,8 +243,7 @@ views::Button* settings_button_ = nullptr; IconButton* up_button_ = nullptr; IconButton* down_button_ = nullptr; - views::View* event_list_container_ = nullptr; - CalendarEventListView* event_list_ = nullptr; + CalendarEventListContainer* event_list_container_ = nullptr; // If it `is_resetting_scroll_`, we don't calculate the scroll position and we // don't need to check if we need to update the month or not.
diff --git a/ash/system/time/calendar_view_unittest.cc b/ash/system/time/calendar_view_unittest.cc index 1cde4df..17d0124d 100644 --- a/ash/system/time/calendar_view_unittest.cc +++ b/ash/system/time/calendar_view_unittest.cc
@@ -124,7 +124,7 @@ IconButton* up_button() { return calendar_view_->up_button_; } IconButton* down_button() { return calendar_view_->down_button_; } views::ImageButton* close_button() { - return calendar_view_->event_list_->close_button_; + return calendar_view_->event_list_container_->event_list()->close_button_; } void ScrollUpOneMonth() { calendar_view_->ScrollUpOneMonthAndAutoScroll(); }
diff --git a/ash/utility/cropping_util.cc b/ash/utility/cropping_util.cc new file mode 100644 index 0000000..ab8f80b --- /dev/null +++ b/ash/utility/cropping_util.cc
@@ -0,0 +1,53 @@ +// Copyright 2022 The Chromium 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/utility/cropping_util.h" + +#include "base/check.h" +#include "base/check_op.h" +#include "base/notreached.h" +#include "base/numerics/safe_conversions.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/geometry/skia_conversions.h" + +namespace ash { + +SkBitmap CenterCropImage(const SkBitmap& image, const gfx::Size& target_size) { + DCHECK(!image.empty()); + DCHECK(!image.isNull()); + DCHECK(!target_size.IsEmpty()); + const int orig_width = image.width(); + const int orig_height = image.height(); + const int new_width = target_size.width(); + const int new_height = target_size.height(); + + // The dimension with the smallest ratio must be cropped, the other + // one is preserved. Both are set in gfx::Size cropped_size. + double horizontal_ratio = + static_cast<double>(new_width) / static_cast<double>(orig_width); + double vertical_ratio = + static_cast<double>(new_height) / static_cast<double>(orig_height); + gfx::Size cropped_size; + if (vertical_ratio > horizontal_ratio) { + cropped_size = + gfx::Size(base::ClampRound(new_width / vertical_ratio), orig_height); + DCHECK_LE(cropped_size.width(), orig_width); + } else { + cropped_size = + gfx::Size(orig_width, base::ClampRound(new_height / horizontal_ratio)); + DCHECK_LE(cropped_size.height(), orig_height); + } + gfx::Rect cropped_rect(orig_width, orig_height); + cropped_rect.ClampToCenteredSize(cropped_size); + SkBitmap sub_image; + if (!image.extractSubset(&sub_image, gfx::RectToSkIRect(cropped_rect))) { + NOTREACHED() << "Cropping image with dimensions " + << gfx::Size(orig_width, orig_height).ToString() << " to " + << cropped_rect.ToString() << " failed."; + } + return sub_image; +} + +} // namespace ash
diff --git a/ash/utility/cropping_util.h b/ash/utility/cropping_util.h new file mode 100644 index 0000000..16eab8de --- /dev/null +++ b/ash/utility/cropping_util.h
@@ -0,0 +1,77 @@ +// Copyright 2022 The Chromium 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_UTILITY_CROPPING_UTIL_H_ +#define ASH_UTILITY_CROPPING_UTIL_H_ + +#include "ash/ash_export.h" +#include "third_party/skia/include/core/SkBitmap.h" + +namespace gfx { +class Size; +} // namespace gfx + +namespace ash { + +// Crops an image such that its aspect ratio matches that of a target size, but +// does not perform any "scaling". The cropping is calculated with the image +// and the target rect "center-aligned". The image dimension with the smaller +// (target_size / original_size) ratio gets cropped. +// +// A visual example with a portrait image whose dimensions exceeds a landscape +// target size: +// +// Before: +// +// Portrait Image +// +---------------------------+ +// | | +// | | +// | | +// | | +// | Landscape Target | +// | +-----------------+ | +// | | | | +// | | | | +// | | | | +// | | | | +// | | | | +// | +-----------------+ | +// | | +// | | +// | | +// | | +// | | +// +---------------------------+ +// +// After (ok, maybe it's not the exact same aspect ratio, but you get the idea): +// +// Cropped Image +// +---------------------------+ +// | | +// | Landscape Target | +// | +-----------------+ | +// | | | | +// | | | | +// | | | | +// | | | | +// | | | | +// | +-----------------+ | +// | | +// | | +// +---------------------------+ +// +// The ultimate result is always a cropped image whose aspect ratio matches that +// of the target size. Therefore, the cropped image can subsequently be scaled +// up or down to match the dimensions of the target size. +// +// There are no requirements for the image and target dimensions other than that +// they're non-empty. This function cannot fail; the returned SkBitmap is always +// non-null and points to ref-counted pixel memory shared with |image|. +ASH_EXPORT SkBitmap CenterCropImage(const SkBitmap& image, + const gfx::Size& target_size); + +} // namespace ash + +#endif // ASH_UTILITY_CROPPING_UTIL_H_
diff --git a/ash/utility/cropping_util_unittest.cc b/ash/utility/cropping_util_unittest.cc new file mode 100644 index 0000000..d80c067 --- /dev/null +++ b/ash/utility/cropping_util_unittest.cc
@@ -0,0 +1,80 @@ +// Copyright 2022 The Chromium 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/utility/cropping_util.h" + +#include "base/logging.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkBitmap.h" +#include "third_party/skia/include/core/SkColor.h" +#include "third_party/skia/include/core/SkRect.h" +#include "ui/gfx/geometry/size.h" +#include "ui/gfx/image/image_unittest_util.h" + +namespace ash { + +namespace { + +SkBitmap CreateTestImage(int width, int height) { + SkBitmap image = gfx::test::CreateBitmap(width, height); + uint32_t pixel_val = 0; + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x, ++pixel_val) { + uint8_t color = pixel_val % std::numeric_limits<uint8_t>::max(); + *(image.getAddr32(x, y)) = SkColorSetARGB(color, color, color, color); + } + } + return image; +} + +} // namespace + +TEST(CroppingUtilTest, CropsLargerPortraitToSmallerLandscape) { + SkBitmap image = CreateTestImage(600, 1200); + SkBitmap cropped_actual = CenterCropImage(image, gfx::Size(300, 200)); + // Cropped dimensions: 600 x 400 + SkBitmap cropped_expected; + ASSERT_TRUE(image.extractSubset(&cropped_expected, + SkIRect::MakeXYWH(0, 400, 600, 400))); + EXPECT_TRUE(gfx::test::AreBitmapsEqual(cropped_actual, cropped_expected)); +} + +TEST(CroppingUtilTest, CropsLargerLandscapeToSmallerPortrait) { + SkBitmap image = CreateTestImage(1200, 600); + SkBitmap cropped_actual = CenterCropImage(image, gfx::Size(200, 300)); + // Cropped dimensions: 400 x 600 + SkBitmap cropped_expected; + ASSERT_TRUE(image.extractSubset(&cropped_expected, + SkIRect::MakeXYWH(400, 0, 400, 600))); + EXPECT_TRUE(gfx::test::AreBitmapsEqual(cropped_actual, cropped_expected)); +} + +TEST(CroppingUtilTest, CropsSmallerPortraitToLargerLandscape) { + SkBitmap image = CreateTestImage(200, 300); + SkBitmap cropped_actual = CenterCropImage(image, gfx::Size(1200, 600)); + // Cropped dimensions: 200 x 100 + SkBitmap cropped_expected; + ASSERT_TRUE(image.extractSubset(&cropped_expected, + SkIRect::MakeXYWH(0, 100, 200, 100))); + EXPECT_TRUE(gfx::test::AreBitmapsEqual(cropped_actual, cropped_expected)); +} + +TEST(CroppingUtilTest, CropsSmallerLandscapeToLargerPortrait) { + SkBitmap image = CreateTestImage(300, 200); + SkBitmap cropped_actual = CenterCropImage(image, gfx::Size(600, 1200)); + // Cropped dimensions: 100 x 200 + SkBitmap cropped_expected; + ASSERT_TRUE(image.extractSubset(&cropped_expected, + SkIRect::MakeXYWH(100, 0, 100, 200))); + EXPECT_TRUE(gfx::test::AreBitmapsEqual(cropped_actual, cropped_expected)); +} + +TEST(CroppingUtilTest, CropsWithIdenticalAspectRatio) { + SkBitmap image = CreateTestImage(600, 1200); + SkBitmap cropped_actual = CenterCropImage(image, gfx::Size(300, 600)); + EXPECT_TRUE(gfx::test::AreBitmapsEqual(cropped_actual, image)); +} + +} // namespace ash
diff --git a/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc index 3828e4c..c7a402a 100644 --- a/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc +++ b/ash/wallpaper/wallpaper_utils/wallpaper_resizer.cc
@@ -6,12 +6,12 @@ #include <utility> +#include "ash/utility/cropping_util.h" #include "ash/wallpaper/wallpaper_utils/wallpaper_resizer_observer.h" #include "base/bind.h" #include "base/location.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" -#include "base/numerics/safe_conversions.h" #include "base/threading/thread_restrictions.h" #include "third_party/skia/include/core/SkImage.h" #include "ui/gfx/geometry/skia_conversions.h" @@ -61,27 +61,9 @@ break; case WALLPAPER_LAYOUT_CENTER_CROPPED: if (orig_width > new_width && orig_height > new_height) { - // The dimension with the smallest ratio must be cropped, the other - // one is preserved. Both are set in gfx::Size cropped_size. - double horizontal_ratio = - static_cast<double>(new_width) / static_cast<double>(orig_width); - double vertical_ratio = static_cast<double>(new_height) / - static_cast<double>(orig_height); - - if (vertical_ratio > horizontal_ratio) { - cropped_size = gfx::Size( - base::ClampRound(new_width / vertical_ratio), orig_height); - } else { - cropped_size = gfx::Size( - orig_width, base::ClampRound(new_height / horizontal_ratio)); - } - wallpaper_rect.ClampToCenteredSize(cropped_size); - SkBitmap sub_image; - orig_bitmap.extractSubset(&sub_image, - gfx::RectToSkIRect(wallpaper_rect)); new_bitmap = skia::ImageOperations::Resize( - sub_image, skia::ImageOperations::RESIZE_LANCZOS3, new_width, - new_height); + CenterCropImage(orig_bitmap, target_size), + skia::ImageOperations::RESIZE_LANCZOS3, new_width, new_height); } break; case NUM_WALLPAPER_LAYOUT:
diff --git a/ash/webui/camera_app_ui/BUILD.gn b/ash/webui/camera_app_ui/BUILD.gn index 547998d..48260fd 100644 --- a/ash/webui/camera_app_ui/BUILD.gn +++ b/ash/webui/camera_app_ui/BUILD.gn
@@ -20,6 +20,8 @@ "camera_app_ui.cc", "camera_app_ui.h", "camera_app_ui_delegate.h", + "camera_app_untrusted_ui.cc", + "camera_app_untrusted_ui.h", "resources.h", "url_constants.cc", "url_constants.h",
diff --git a/ash/webui/camera_app_ui/camera_app_ui.cc b/ash/webui/camera_app_ui/camera_app_ui.cc index 623f4678..4673564 100644 --- a/ash/webui/camera_app_ui/camera_app_ui.cc +++ b/ash/webui/camera_app_ui/camera_app_ui.cc
@@ -74,32 +74,6 @@ return source; } -content::WebUIDataSource* CreateUntrustedCameraAppUIHTMLSource() { - content::WebUIDataSource* untrusted_source = - content::WebUIDataSource::Create(kChromeUIUntrustedCameraAppURL); - for (size_t i = 0; i < kAshCameraAppResourcesSize; i++) { - untrusted_source->AddResourcePath(kAshCameraAppResources[i].path, - kAshCameraAppResources[i].id); - } - untrusted_source->AddFrameAncestor(GURL(kChromeUICameraAppURL)); - - untrusted_source->OverrideContentSecurityPolicy( - network::mojom::CSPDirectiveName::ConnectSrc, - std::string("connect-src http://www.google-analytics.com/ 'self';")); - untrusted_source->OverrideContentSecurityPolicy( - network::mojom::CSPDirectiveName::WorkerSrc, - std::string("worker-src 'self';")); - // TODO(crbug/948834): Replace 'wasm-eval' with 'wasm-unsafe-eval'. - untrusted_source->OverrideContentSecurityPolicy( - network::mojom::CSPDirectiveName::ScriptSrc, - std::string("script-src 'self' 'wasm-eval';")); - untrusted_source->OverrideContentSecurityPolicy( - network::mojom::CSPDirectiveName::TrustedTypes, - std::string("trusted-types ga-js-static video-processor-js-static;")); - - return untrusted_source; -} - // Translates the renderer-side source ID to video device id. void TranslateVideoDeviceId( const std::string& salt, @@ -213,8 +187,6 @@ // Set up the data source. content::WebUIDataSource::Add(browser_context, CreateCameraAppUIHTMLSource(delegate_.get())); - content::WebUIDataSource::Add(browser_context, - CreateUntrustedCameraAppUIHTMLSource()); // Add ability to request chrome-untrusted: URLs web_ui->AddRequestableScheme(content::kChromeUIUntrustedScheme);
diff --git a/ash/webui/camera_app_ui/camera_app_untrusted_ui.cc b/ash/webui/camera_app_ui/camera_app_untrusted_ui.cc new file mode 100644 index 0000000..4acfd6a1 --- /dev/null +++ b/ash/webui/camera_app_ui/camera_app_untrusted_ui.cc
@@ -0,0 +1,58 @@ +// Copyright 2022 The Chromium 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/webui/camera_app_ui/camera_app_untrusted_ui.h" + +#include <string> + +#include "ash/webui/camera_app_ui/url_constants.h" +#include "ash/webui/grit/ash_camera_app_resources_map.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" +#include "services/network/public/mojom/content_security_policy.mojom.h" +#include "url/gurl.h" + +namespace ash { + +namespace { + +content::WebUIDataSource* CreateUntrustedCameraAppUIHTMLSource() { + content::WebUIDataSource* untrusted_source = + content::WebUIDataSource::Create(kChromeUIUntrustedCameraAppURL); + untrusted_source->AddResourcePaths( + base::make_span(kAshCameraAppResources, kAshCameraAppResourcesSize)); + untrusted_source->AddFrameAncestor(GURL(kChromeUICameraAppURL)); + + untrusted_source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ConnectSrc, + std::string("connect-src http://www.google-analytics.com/ 'self';")); + untrusted_source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::WorkerSrc, + std::string("worker-src 'self';")); + // TODO(crbug/948834): Replace 'wasm-eval' with 'wasm-unsafe-eval'. + untrusted_source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, + std::string("script-src 'self' 'wasm-eval';")); + untrusted_source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::TrustedTypes, + std::string("trusted-types ga-js-static video-processor-js-static;")); + + return untrusted_source; +} + +} // namespace + +CameraAppUntrustedUI::CameraAppUntrustedUI(content::WebUI* web_ui) + : ui::UntrustedWebUIController(web_ui) { + content::WebUIDataSource* untrusted_source = + CreateUntrustedCameraAppUIHTMLSource(); + + auto* browser_context = web_ui->GetWebContents()->GetBrowserContext(); + content::WebUIDataSource::Add(browser_context, untrusted_source); +} + +CameraAppUntrustedUI::~CameraAppUntrustedUI() = default; + +} // namespace ash
diff --git a/ash/webui/camera_app_ui/camera_app_untrusted_ui.h b/ash/webui/camera_app_ui/camera_app_untrusted_ui.h new file mode 100644 index 0000000..c435804 --- /dev/null +++ b/ash/webui/camera_app_ui/camera_app_untrusted_ui.h
@@ -0,0 +1,23 @@ +// Copyright 2022 The Chromium 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_WEBUI_CAMERA_APP_UI_CAMERA_APP_UNTRUSTED_UI_H_ +#define ASH_WEBUI_CAMERA_APP_UI_CAMERA_APP_UNTRUSTED_UI_H_ + +#include "ui/webui/untrusted_web_ui_controller.h" + +namespace ash { + +// The Web UI for chrome-untrusted://camera-app. +class CameraAppUntrustedUI : public ui::UntrustedWebUIController { + public: + explicit CameraAppUntrustedUI(content::WebUI* web_ui); + CameraAppUntrustedUI(const CameraAppUntrustedUI&) = delete; + CameraAppUntrustedUI& operator=(const CameraAppUntrustedUI&) = delete; + ~CameraAppUntrustedUI() override; +}; + +} // namespace ash + +#endif // ASH_WEBUI_CAMERA_APP_UI_CAMERA_APP_UNTRUSTED_UI_H_ \ No newline at end of file
diff --git a/ash/webui/camera_app_ui/resources/js/main.ts b/ash/webui/camera_app_ui/resources/js/main.ts index 41a0d50b..0522694 100644 --- a/ash/webui/camera_app_ui/resources/js/main.ts +++ b/ash/webui/camera_app_ui/resources/js/main.ts
@@ -18,7 +18,6 @@ import * as loadTimeData from './models/load_time_data.js'; import * as localStorage from './models/local_storage.js'; import {ChromeHelper} from './mojo/chrome_helper.js'; -import {notifyCameraResourceReady} from './mojo/device_operator.js'; import * as nav from './nav.js'; import {PerfLogger} from './perf.js'; import {preloadImagesList} from './preload_images.js'; @@ -238,7 +237,6 @@ } else { // CCA must get camera usage for completing its initialization when // first launched. - notifyCameraResourceReady(); await this.cameraManager.initialize(this.cameraView); await this.cameraView.initialize(); cameraResourceInitialized.signal();
diff --git a/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts b/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts index e3547023..fb6906c8 100644 --- a/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts +++ b/ash/webui/camera_app_ui/resources/js/mojo/device_operator.ts
@@ -15,7 +15,7 @@ ResolutionList, VideoConfig, } from '../type.js'; -import {CancelableEvent, WaitableEvent} from '../waitable_event.js'; +import {CancelableEvent} from '../waitable_event.js'; import { AndroidInfoSupportedHardwareLevel, @@ -114,23 +114,11 @@ let instance: DeviceOperator|null = null; /** - * A ready event which should be signaled once the camera resource is ready. - */ -const readyEvent = new WaitableEvent(); - -/** * Job queue to sequentialize devices operations. */ const operationQueue = new AsyncJobQueue(); /** - * Notified when the camera resource is ready. - */ -export function notifyCameraResourceReady(): void { - readyEvent.signal(); -} - -/** * Operates video capture device through CrOS Camera App Mojo interface. */ export class DeviceOperator { @@ -687,7 +675,6 @@ * @return The singleton instance. */ static async getInstance(): Promise<DeviceOperator|null> { - await readyEvent.wait(); if (instance === null) { instance = new DeviceOperator(); }
diff --git a/ash/webui/personalization_app/resources/common/styles.html b/ash/webui/personalization_app/resources/common/styles.html index 78291781c..c49da72 100644 --- a/ash/webui/personalization_app/resources/common/styles.html +++ b/ash/webui/personalization_app/resources/common/styles.html
@@ -230,5 +230,9 @@ cr-button + cr-button { margin-inline-start: 8px; } + .preview-container { + border: 1px solid rgba(0, 0, 0, 0.08); + border-radius: 16px; + } </style> </template>
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html b/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html index f880a60..19c24be 100644 --- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html +++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.html
@@ -1,5 +1,6 @@ -<style></style> -<div id="container"> +<style include="common-style"> +</style> +<div class="preview-container" id="container"> <slot></slot> <div id="imageContainer"></div> <div id="description"></div>
diff --git a/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.ts b/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.ts index a82c957..c97e258 100644 --- a/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.ts +++ b/ash/webui/personalization_app/resources/trusted/ambient/ambient_preview_element.ts
@@ -7,6 +7,9 @@ * screensaver. */ +import 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import '../../common/styles.js'; + import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; export class AmbientPreview extends PolymerElement {
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_main_element.html b/ash/webui/personalization_app/resources/trusted/personalization_main_element.html index 3f8c7a6..b43aad6 100644 --- a/ash/webui/personalization_app/resources/trusted/personalization_main_element.html +++ b/ash/webui/personalization_app/resources/trusted/personalization_main_element.html
@@ -1,4 +1,38 @@ <style> + #container { + display: grid; + grid-template-areas: + '. leftspacer userpreview userpreview rightspacer .' + '. leftspacer . . rightspacer .' + '. leftspacer wallpaper screensaver rightspacer .' + '. leftspacer . . rightspacer .'; + grid-template-columns: 1fr 72px minmax(240px, 480px) minmax(240px, 480px) 72px 1fr; + grid-template-rows: 108px 12px 1fr 12px; + height: 100%; + position: relative; + width: 100%; + } + + #leftspacer { + grid-area: leftspacer; + } + + #rightspacer { + grid-area: rightspacer; + } + + user-preview { + grid-area: userpreview; + } + + wallpaper-preview { + grid-area: wallpaper; + } + + ambient-preview { + grid-area: screensaver; + } + #ambientSubpageLink { background: none; border: none; @@ -10,19 +44,21 @@ } </style> <div id="container"> - <h1>Personalization</h1> + <div id="leftspacer"></div> <user-preview> <cr-icon-button id="userSubpageLink" iron-icon="personalization:pencil" on-click="onClickUserSubpageLink_"></cr-icon-button> </user-preview> - <wallpaper-preview></wallpaper-preview> + <wallpaper-preview> + <template is="dom-if" if="[[isDarkLightModeEnabled_()]]"> + <personalization-theme></personalization-theme> + </template> + </wallpaper-preview> <ambient-preview> <cr-button id="ambientSubpageLink" on-click="onClickAmbientSubpageLink_"> <div class="text">Screensaver</div> <iron-icon icon="cr:chevron-right" aria-hidden="true"></iron-icon> </cr-button> </ambient-preview> - <template is="dom-if" if="[[isDarkLightModeEnabled_()]]"> - <personalization-theme></personalization-theme> - </template> + <div id="rightspacer"></div> </div>
diff --git a/ash/webui/personalization_app/resources/trusted/personalization_reducers.ts b/ash/webui/personalization_app/resources/trusted/personalization_reducers.ts index 5c7c60f..93ef046d 100644 --- a/ash/webui/personalization_app/resources/trusted/personalization_reducers.ts +++ b/ash/webui/personalization_app/resources/trusted/personalization_reducers.ts
@@ -16,7 +16,7 @@ import {AmbientState} from './ambient/ambient_state.js'; import {PersonalizationActionName} from './personalization_actions.js'; import {Actions} from './personalization_actions.js'; -import {WallpaperImage} from './personalization_app.mojom-webui.js'; +import {GooglePhotosPhoto, WallpaperImage} from './personalization_app.mojom-webui.js'; import {PersonalizationState} from './personalization_state.js'; import {themeReducers} from './theme/theme_reducers.js'; import {ThemeState} from './theme/theme_state.js'; @@ -26,7 +26,7 @@ import {wallpaperReducers} from './wallpaper/wallpaper_reducers.js'; import {WallpaperState} from './wallpaper/wallpaper_state.js'; -export type DisplayableImage = FilePath|WallpaperImage; +export type DisplayableImage = FilePath|GooglePhotosPhoto|WallpaperImage; export type ReducerFunction<State> = (state: State, action: Actions, globalState: PersonalizationState) => State;
diff --git a/ash/webui/personalization_app/resources/trusted/utils.ts b/ash/webui/personalization_app/resources/trusted/utils.ts index 16d41568..cac3182 100644 --- a/ash/webui/personalization_app/resources/trusted/utils.ts +++ b/ash/webui/personalization_app/resources/trusted/utils.ts
@@ -8,7 +8,7 @@ import {FilePath} from 'chrome://resources/mojo/mojo/public/mojom/base/file_path.mojom-webui.js'; -import {WallpaperImage, WallpaperLayout} from '../trusted/personalization_app.mojom-webui.js'; +import {GooglePhotosPhoto, WallpaperImage, WallpaperLayout} from '../trusted/personalization_app.mojom-webui.js'; export function isWallpaperImage(obj: any): obj is WallpaperImage { return typeof obj?.assetId === 'bigint'; @@ -18,6 +18,11 @@ return typeof obj?.path === 'string' && obj.path; } +/** Checks whether |obj| is an instance of |GooglePhotosPhoto|. */ +export function isGooglePhotosPhoto(obj: any): obj is GooglePhotosPhoto { + return typeof obj?.id === 'string'; +} + /** * Convert a string layout value to the corresponding enum. */
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.html index 53c7b0ed..270826dc 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.html +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.html
@@ -13,6 +13,8 @@ <wallpaper-grid-item class="photo" image-src="[[photo.url.url]]" + on-click="onPhotoSelected_" + on-keypress="onPhotoSelected_" tabindex$="[[tabIndex]]"> </wallpaper-grid-item> </template>
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.ts index d1a266d2..5c329d6c 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_by_album_id_element.ts
@@ -10,14 +10,15 @@ import './styles.js'; import '/common/styles.js'; +import {assert} from 'chrome://resources/js/assert.m.js'; import {IronListElement} from 'chrome://resources/polymer/v3_0/iron-list/iron-list.js'; import {afterNextRender, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {isNonEmptyArray} from '../../common/utils.js'; +import {isNonEmptyArray, isSelectionEvent} from '../../common/utils.js'; import {GooglePhotosPhoto, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js'; import {PersonalizationStore, WithPersonalizationStore} from '../personalization_store.js'; -import {fetchGooglePhotosAlbum} from './wallpaper_controller.js'; +import {fetchGooglePhotosAlbum, selectWallpaper} from './wallpaper_controller.js'; import {getWallpaperProvider} from './wallpaper_interface_provider.js'; export interface GooglePhotosPhotosByAlbumId { @@ -101,6 +102,14 @@ afterNextRender(this, () => this.$.grid.fire('iron-resize')); } + /** Invoked on selection of a photo. */ + private onPhotoSelected_(e: Event&{model: {photo: GooglePhotosPhoto}}) { + assert(e.model.photo); + if (isSelectionEvent(e)) { + selectWallpaper(e.model.photo, this.wallpaperProvider_, this.getStore()); + } + } + /** Invoked to compute |album_|. */ private computeAlbum_(): GooglePhotosPhoto[]|null { // If no album is currently selected or if the currently selected album is
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.html index 84886b5..42cf2c84 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.html +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.html
@@ -29,6 +29,8 @@ class="photo" colindex$="[[index]]" image-src="[[photo.url.url]]" + on-click="onPhotoSelected_" + on-keypress="onPhotoSelected_" tabindex="-1"> </wallpaper-grid-item> </template>
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.ts index 04b6f96..7c7a4950 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/google_photos_photos_element.ts
@@ -15,9 +15,12 @@ import {afterNextRender, html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getNumberOfGridItemsPerRow, isNonEmptyArray, isSelectionEvent, normalizeKeyForRTL} from '../../common/utils.js'; -import {GooglePhotosPhoto} from '../personalization_app.mojom-webui.js'; +import {GooglePhotosPhoto, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js'; import {WithPersonalizationStore} from '../personalization_store.js'; +import {selectWallpaper} from './wallpaper_controller.js'; +import {getWallpaperProvider} from './wallpaper_interface_provider.js'; + export interface GooglePhotosPhotos { $: {grid: IronListElement;}; } @@ -84,6 +87,10 @@ /** The number of photos to render per row in a grid. */ private photosPerRow_: number; + /** The singleton wallpaper provider interface. */ + private wallpaperProvider_: WallpaperProviderInterface = + getWallpaperProvider(); + connectedCallback() { super.connectedCallback(); @@ -159,6 +166,14 @@ } } + /** Invoked on selection of a photo. */ + private onPhotoSelected_(e: Event&{model: {photo: GooglePhotosPhoto}}) { + assert(e.model.photo); + if (isSelectionEvent(e)) { + selectWallpaper(e.model.photo, this.wallpaperProvider_, this.getStore()); + } + } + /** Invoked on resize of this element. */ private onResized_() { this.photosPerRow_ = getNumberOfGridItemsPerRow();
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.ts index 9f419185..3c4a67ed 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/local_images_element.ts
@@ -21,7 +21,7 @@ import {getLoadingPlaceholderAnimationDelay} from '../../common/utils.js'; import {isSelectionEvent} from '../../common/utils.js'; -import {CurrentWallpaper, WallpaperImage, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js'; +import {CurrentWallpaper, GooglePhotosPhoto, WallpaperImage, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js'; import {WithPersonalizationStore} from '../personalization_store.js'; import {isFilePath} from '../utils.js'; @@ -80,7 +80,7 @@ private imageData_: Record<FilePath['path'], string>; private imageDataLoading_: Record<FilePath['path'], boolean>; private currentSelected_: CurrentWallpaper|null; - private pendingSelected_: FilePath|WallpaperImage|null; + private pendingSelected_: FilePath|GooglePhotosPhoto|WallpaperImage|null; private imagesToDisplay_: FilePath[]; constructor() {
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_controller.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_controller.ts index 2cf5ad3..3a9d0c1 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_controller.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_controller.ts
@@ -9,7 +9,7 @@ import {isNonEmptyArray} from '../../common/utils.js'; import {FetchGooglePhotosAlbumsResponse, FetchGooglePhotosPhotosResponse, GooglePhotosAlbum, GooglePhotosPhoto, WallpaperCollection, WallpaperImage, WallpaperLayout, WallpaperProviderInterface, WallpaperType} from '../personalization_app.mojom-webui.js'; import {PersonalizationStore} from '../personalization_store.js'; -import {isFilePath, isWallpaperImage} from '../utils.js'; +import {isFilePath, isGooglePhotosPhoto, isWallpaperImage} from '../utils.js'; import * as action from './wallpaper_actions.js'; @@ -212,8 +212,8 @@ } export async function selectWallpaper( - image: WallpaperImage|FilePath, provider: WallpaperProviderInterface, - store: PersonalizationStore, + image: WallpaperImage|FilePath|GooglePhotosPhoto, + provider: WallpaperProviderInterface, store: PersonalizationStore, layout: WallpaperLayout = WallpaperLayout.kCenterCropped): Promise<void> { // Batch these changes together to reduce polymer churn as multiple state // fields change quickly. @@ -231,6 +231,9 @@ } else if (isFilePath(image)) { return provider.selectLocalImage( image, layout, /*preview_mode=*/ shouldPreview); + } else if (isGooglePhotosPhoto(image)) { + // TODO(b/218331763): Replace with mojo interface call. + return {success: false}; } else { console.warn('Image must be a local image or a WallpaperImage'); return {success: false};
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_fullscreen_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_fullscreen_element.ts index 9e3a5723..288c3b8 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_fullscreen_element.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_fullscreen_element.ts
@@ -15,7 +15,7 @@ import {FilePath} from 'chrome://resources/mojo/mojo/public/mojom/base/file_path.mojom-webui.js'; import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; -import {CurrentWallpaper, WallpaperImage, WallpaperLayout, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js'; +import {CurrentWallpaper, GooglePhotosPhoto, WallpaperImage, WallpaperLayout, WallpaperProviderInterface} from '../personalization_app.mojom-webui.js'; import {WithPersonalizationStore} from '../personalization_store.js'; import {getWallpaperLayoutEnum} from '../utils.js'; import {isFilePath} from '../utils.js'; @@ -66,7 +66,8 @@ private visible_: boolean = false; private showLayoutOptions_: boolean = false; private currentSelected_: CurrentWallpaper|null = null; - private pendingSelected_: FilePath|WallpaperImage|null = null; + private pendingSelected_: FilePath|GooglePhotosPhoto|WallpaperImage|null = + null; private selectedLayout_: WallpaperLayout|null = null; private wallpaperProvider_: WallpaperProviderInterface;
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html index b693f08d..89435e1 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.html
@@ -1,4 +1,4 @@ -<style> +<style include="common-style"> #wallpaperLabel { background: none; border: none; @@ -9,15 +9,18 @@ width: 20px; } </style> -<cr-button id="wallpaperLabel" on-click="onClickWallpaper_"> - <div class="text">[[i18n('wallpaperLabel')]]</div> - <iron-icon icon="cr:chevron-right" aria-hidden="true"></iron-icon> -</cr-button> -<template is="dom-if" if="[[showPlaceholders_(isLoading_, showImage_)]]"> - <div id="imagePlaceholder"></div> -</template> -<template is="dom-if" if="[[showImage_]]"> - <div id="imageContainer"> - <img src="[[getImageSrc_(image_)]]" aria-hidden="true"> - </div> -</template> +<div class="preview-container" id="container"> + <cr-button id="wallpaperLabel" on-click="onClickWallpaper_"> + <div class="text">[[i18n('wallpaperLabel')]]</div> + <iron-icon icon="cr:chevron-right" aria-hidden="true"></iron-icon> + </cr-button> + <template is="dom-if" if="[[showPlaceholders_(isLoading_, showImage_)]]"> + <div id="imagePlaceholder"></div> + </template> + <template is="dom-if" if="[[showImage_]]"> + <div id="imageContainer"> + <img src="[[getImageSrc_(image_)]]" aria-hidden="true"> + </div> + </template> + <slot></slot> +</div>
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts index 7fdc967..42c80af 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_preview_element.ts
@@ -10,6 +10,7 @@ import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import 'chrome://resources/polymer/v3_0/iron-icon/iron-icon.js'; import '/common/icons.js'; +import '/common/styles.js'; import './styles.js'; import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
diff --git a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_state.ts b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_state.ts index 046056cc..364854c 100644 --- a/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_state.ts +++ b/ash/webui/personalization_app/resources/trusted/wallpaper/wallpaper_state.ts
@@ -82,7 +82,7 @@ loading: LoadingState; local: LocalState; currentSelected: CurrentWallpaper|null; - pendingSelected: WallpaperImage|FilePath|null; + pendingSelected: WallpaperImage|FilePath|GooglePhotosPhoto|null; dailyRefresh: DailyRefreshState; fullscreen: boolean; googlePhotos: GooglePhotosState;
diff --git a/ash/webui/personalization_app/test/personalization_app_browsertest.js b/ash/webui/personalization_app/test/personalization_app_browsertest.js index 3805323..390ca92 100644 --- a/ash/webui/personalization_app/test/personalization_app_browsertest.js +++ b/ash/webui/personalization_app/test/personalization_app_browsertest.js
@@ -86,15 +86,22 @@ this[PersonalizationAppBrowserTest.name] = PersonalizationAppBrowserTest; // Tests that chrome://personalization loads the page without javascript errors -// or a 404 or crash. Should display some text. +// or a 404 or crash. Displays user preview, wallpaper preview, and ambient +// preview TEST_F('PersonalizationAppBrowserTest', 'HasRootPageUrl', () => { assertEquals(document.location.href, ROOT_PAGE); - assertEquals( - 'Personalization', - document.querySelector('personalization-router') - .shadowRoot.querySelector('personalization-main') - .shadowRoot.querySelector('h1') - .innerText); + const userPreview = document.querySelector('personalization-router') + .shadowRoot.querySelector('personalization-main') + .shadowRoot.querySelector('user-preview'); + const wallpaperPreview = document.querySelector('personalization-router') + .shadowRoot.querySelector('personalization-main') + .shadowRoot.querySelector('wallpaper-preview'); + const ambientPreview = document.querySelector('personalization-router') + .shadowRoot.querySelector('personalization-main') + .shadowRoot.querySelector('ambient-preview'); + assertTrue(!!userPreview); + assertTrue(!!wallpaperPreview); + assertTrue(!!ambientPreview); testDone(); }); @@ -159,7 +166,7 @@ // somewhere instead of 404ing or crashing. TEST_F('WallpaperSubpageBrowserTest', 'HasWallpaperSubpageUrl', () => { assertEquals(document.location.href, WALLPAPER_SUBPAGE); - + const title = document.querySelector('head > title'); assertEquals('Wallpaper', title.innerText); testDone();
diff --git a/ash/wm/client_controlled_state.cc b/ash/wm/client_controlled_state.cc index 8476543..e18c9dc 100644 --- a/ash/wm/client_controlled_state.cc +++ b/ash/wm/client_controlled_state.cc
@@ -95,16 +95,13 @@ case WM_EVENT_MINIMIZE: case WM_EVENT_FULLSCREEN: case WM_EVENT_SNAP_PRIMARY: - case WM_EVENT_SNAP_SECONDARY: { + case WM_EVENT_SNAP_SECONDARY: + case WM_EVENT_RESTORE: { WindowStateType next_state = GetResolvedNextWindowStateType(window_state, event); UpdateWindowForTransitionEvents(window_state, next_state, event_type); break; } - case WM_EVENT_RESTORE: - UpdateWindowForTransitionEvents( - window_state, window_state->GetRestoreWindowState(), event_type); - break; case WM_EVENT_SHOW_INACTIVE: NOTREACHED(); break; @@ -300,8 +297,20 @@ const WindowStateType next = GetStateForTransitionEvent(window_state, event); if (Shell::Get()->tablet_mode_controller()->InTabletMode() && - next == WindowStateType::kNormal && window_state->CanMaximize()) + next == WindowStateType::kNormal && window_state->CanMaximize()) { return WindowStateType::kMaximized; + } + + // For app-requested fullscreen, don't allow it to restore back to kMaximized + // window state due to some restrictions on ARC++ side. see b/215710461 for + // details. This is a stopgap fix for M99. And we should revisit this behavior + // later and see if we can remove this restrictions. + const WMEventType type = event->type(); + if ((type == WM_EVENT_RESTORE || type == WM_EVENT_NORMAL) && + state_type_ == WindowStateType::kFullscreen && + next == WindowStateType::kMaximized) { + return WindowStateType::kNormal; + } return next; }
diff --git a/ash/wm/client_controlled_state_unittest.cc b/ash/wm/client_controlled_state_unittest.cc index ec89ac5..c15bdec7 100644 --- a/ash/wm/client_controlled_state_unittest.cc +++ b/ash/wm/client_controlled_state_unittest.cc
@@ -629,4 +629,29 @@ EXPECT_EQ(WindowStateType::kMaximized, delegate()->new_state()); } +// Tests the restore behavior for fullscreen window. For fullscreen window, for +// now it can only restore back to kNormal window state. Note: this behavior +// may change after M99, see b/215710461. +TEST_F(ClientControlledStateTest, FullscreenRestore) { + widget()->Maximize(); + EXPECT_FALSE(widget()->IsMaximized()); + state()->EnterNextState(window_state(), delegate()->new_state()); + EXPECT_TRUE(widget()->IsMaximized()); + + widget()->SetFullscreen(true); + EXPECT_TRUE(widget()->IsMaximized()); + EXPECT_EQ(WindowStateType::kMaximized, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kFullscreen, delegate()->new_state()); + state()->EnterNextState(window_state(), delegate()->new_state()); + EXPECT_TRUE(widget()->IsFullscreen()); + + widget()->Restore(); + EXPECT_TRUE(widget()->IsFullscreen()); + EXPECT_EQ(WindowStateType::kFullscreen, delegate()->old_state()); + EXPECT_EQ(WindowStateType::kNormal, delegate()->new_state()); + state()->EnterNextState(window_state(), delegate()->new_state()); + EXPECT_FALSE(widget()->IsMaximized()); + EXPECT_FALSE(widget()->IsFullscreen()); +} + } // namespace ash
diff --git a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java index 16126e8..d0f74c0c 100644 --- a/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java +++ b/base/android/java/src/org/chromium/base/ApiCompatibilityUtils.java
@@ -167,7 +167,6 @@ } @VerifiesOnLollipopMR1 - @TargetApi(Build.VERSION_CODES.LOLLIPOP_MR1) private static class ApisLmr1 { static void setAccessibilityTraversalBefore(View view, int viewFocusedAfter) { view.setAccessibilityTraversalBefore(viewFocusedAfter);
diff --git a/base/android/java/src/org/chromium/base/LocaleUtils.java b/base/android/java/src/org/chromium/base/LocaleUtils.java index 80f141b..ac87642 100644 --- a/base/android/java/src/org/chromium/base/LocaleUtils.java +++ b/base/android/java/src/org/chromium/base/LocaleUtils.java
@@ -61,7 +61,6 @@ * @return a locale with updated language codes for Chromium, with translated modern language * codes used by Chromium. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) @VisibleForTesting public static Locale getUpdatedLocaleForChromium(Locale locale) { String language = locale.getLanguage(); @@ -95,7 +94,6 @@ * @return a locale with updated language codes for Android, from translated modern language * codes used by Chromium. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) @VisibleForTesting public static Locale getUpdatedLocaleForAndroid(Locale locale) { String language = locale.getLanguage();
diff --git a/base/android/java/src/org/chromium/base/PowerMonitor.java b/base/android/java/src/org/chromium/base/PowerMonitor.java index 964bf20..cb00302 100644 --- a/base/android/java/src/org/chromium/base/PowerMonitor.java +++ b/base/android/java/src/org/chromium/base/PowerMonitor.java
@@ -4,7 +4,6 @@ package org.chromium.base; -import android.annotation.TargetApi; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; @@ -96,7 +95,6 @@ return getRemainingBatteryCapacityImpl(); } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) private static int getRemainingBatteryCapacityImpl() { return ((BatteryManager) ContextUtils.getApplicationContext().getSystemService( Context.BATTERY_SERVICE))
diff --git a/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java b/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java index e19e260..ec3a6ff 100644 --- a/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java +++ b/base/android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java
@@ -4,7 +4,6 @@ package org.chromium.base; -import android.annotation.TargetApi; import android.app.Activity; import android.os.Build; import android.os.SystemClock; @@ -31,7 +30,6 @@ int mFinishCallbackCount; boolean mIsFinishing; - @TargetApi(Build.VERSION_CODES.LOLLIPOP) @Override public void finishAndRemoveTask() { mFinishAndRemoveTaskCallbackCount++;
diff --git a/base/metrics/persistent_histogram_allocator.cc b/base/metrics/persistent_histogram_allocator.cc index 3662d189..b8c04be 100644 --- a/base/metrics/persistent_histogram_allocator.cc +++ b/base/metrics/persistent_histogram_allocator.cc
@@ -104,8 +104,15 @@ } // namespace -const Feature kPersistentHistogramsFeature{"PersistentHistograms", - FEATURE_ENABLED_BY_DEFAULT}; +const Feature kPersistentHistogramsFeature{ + "PersistentHistograms", +#if BUILDFLAG(IS_FUCHSIA) + // TODO(crbug.com/1295119): Enable once writable mmap() is supported. + FEATURE_DISABLED_BY_DEFAULT +#else + FEATURE_ENABLED_BY_DEFAULT +#endif // BUILDFLAG(IS_FUCHSIA) +}; PersistentSparseHistogramDataManager::PersistentSparseHistogramDataManager( PersistentMemoryAllocator* allocator)
diff --git a/base/path_service_unittest.cc b/base/path_service_unittest.cc index b756822f..1f15603 100644 --- a/base/path_service_unittest.cc +++ b/base/path_service_unittest.cc
@@ -114,7 +114,7 @@ // crbug.com/1257402). Current implementation is described before each key. // TODO(crbug.com/1257402): Remove the definition of these keys on Android // or at least fix the behavior of DIR_HOME. - constexpr std::array<int, 2> kUnsupportedKeys = { + constexpr std::array kUnsupportedKeys = { // Though DIR_HOME is not intended to be supported, PathProviderPosix // handles it and returns true. Thus, it is NOT included in the array. /* DIR_HOME, */ @@ -123,16 +123,16 @@ // PathProviderPosix handles it but fails at some point. DIR_USER_DESKTOP}; #elif BUILDFLAG(IS_IOS) - constexpr std::array<int, 1> kUnsupportedKeys = { + constexpr std::array kUnsupportedKeys = { // DIR_USER_DESKTOP is not implemented on iOS. See crbug.com/1257402. DIR_USER_DESKTOP}; #elif BUILDFLAG(IS_FUCHSIA) - constexpr std::array<int, 3> kUnsupportedKeys = { + constexpr std::array kUnsupportedKeys = { // TODO(crbug.com/1231928): Implement DIR_USER_DESKTOP. DIR_USER_DESKTOP}; #else - constexpr std::array<int, 0> kUnsupportedKeys = {}; + constexpr std::array<BasePathKey, 0> kUnsupportedKeys = {}; #endif // BUILDFLAG(IS_ANDROID) for (int key = PATH_START + 1; key < PATH_END; ++key) { if (std::find(kUnsupportedKeys.begin(), kUnsupportedKeys.end(), key) ==
diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java index 527e007e2..8b4000e 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java +++ b/base/test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java
@@ -4,7 +4,6 @@ package org.chromium.base.test; -import android.annotation.TargetApi; import android.app.Activity; import android.app.ActivityManager; import android.app.Application; @@ -542,7 +541,6 @@ } /** Finishes all tasks Chrome has listed in Android's Overview. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) private void finishAllAppTasks(final Context context) { // Close all of the tasks one by one. ActivityManager activityManager =
diff --git a/base/tracing/protos/chrome_track_event.proto b/base/tracing/protos/chrome_track_event.proto index b43bd18..1984ebc 100644 --- a/base/tracing/protos/chrome_track_event.proto +++ b/base/tracing/protos/chrome_track_event.proto
@@ -130,6 +130,7 @@ SHOULD_SWAP_BROWSING_INSTANCE_NO_HAS_NOT_COMMITTED_ANY_NAVIGATION = 20; SHOULD_SWAP_BROWSING_INSTANCE_NO_UNLOAD_HANDLER_EXISTS_ON_SAME_SITE_NAVIGATION = 21; + SHOULD_SWAP_BROWSING_INSTANCE_NO_NOT_PRIMARY_MAIN_FRAME = 22; } message ShouldSwapBrowsingInstancesResult {
diff --git a/base/values.cc b/base/values.cc index 53622114..7559386 100644 --- a/base/values.cc +++ b/base/values.cc
@@ -1338,29 +1338,17 @@ ListValue::ListValue(ListStorage&& in_list) noexcept : Value(std::move(in_list)) {} -bool ListValue::Get(size_t index, const Value** out_value) const { - if (index >= list().size()) - return false; - - if (out_value) - *out_value = &list()[index]; - - return true; -} - -bool ListValue::Get(size_t index, Value** out_value) { - return as_const(*this).Get(index, const_cast<const Value**>(out_value)); -} - bool ListValue::GetDictionary(size_t index, const DictionaryValue** out_value) const { - const Value* value; - bool result = Get(index, &value); - if (!result || !value->is_dict()) + const auto& list = GetListDeprecated(); + if (list.size() <= index) + return false; + const base::Value& value = list[index]; + if (!value.is_dict()) return false; if (out_value) - *out_value = static_cast<const DictionaryValue*>(value); + *out_value = static_cast<const DictionaryValue*>(&value); return true; }
diff --git a/base/values.h b/base/values.h index 99b3d7e..95a5fcf 100644 --- a/base/values.h +++ b/base/values.h
@@ -795,14 +795,6 @@ explicit ListValue(span<const Value> in_list); explicit ListValue(ListStorage&& in_list) noexcept; - // Gets the Value at the given index. Modifies `out_value` (and returns true) - // only if the index falls within the current list range. - // Note that the list always owns the Value passed out via `out_value`. - // `out_value` is optional and will only be set if non-NULL. - // DEPRECATED, use `GetListDeprecated()::operator[] instead. - bool Get(size_t index, const Value** out_value) const; - bool Get(size_t index, Value** out_value); - // Convenience forms of `Get()`. Modifies `out_value` (and returns true) // only if the index is valid and the Value at that index can be returned // in the specified form.
diff --git a/base/values_unittest.cc b/base/values_unittest.cc index 0a726474..09048ff 100644 --- a/base/values_unittest.cc +++ b/base/values_unittest.cc
@@ -1534,8 +1534,8 @@ dict.Set("this.is.expanded", std::make_unique<Value>()); dict.SetKey("this.isnt.expanded", Value()); - EXPECT_FALSE(dict.HasKey("this.is.expanded")); - EXPECT_TRUE(dict.HasKey("this")); + EXPECT_FALSE(dict.FindKey("this.is.expanded")); + EXPECT_TRUE(dict.FindKey("this")); Value* value1; EXPECT_TRUE(dict.Get("this", &value1)); DictionaryValue* value2; @@ -1543,7 +1543,7 @@ EXPECT_EQ(value1, value2); EXPECT_EQ(1U, value2->DictSize()); - EXPECT_TRUE(dict.HasKey("this.isnt.expanded")); + EXPECT_TRUE(dict.FindKey("this.isnt.expanded")); Value* value3; EXPECT_FALSE(dict.Get("this.isnt.expanded", &value3)); Value* value4 = dict.FindKey("this.isnt.expanded"); @@ -1558,8 +1558,8 @@ dict.Set("this.is.expanded", std::make_unique<Value>()); dict.SetWithoutPathExpansion("this.isnt.expanded", std::make_unique<Value>()); - EXPECT_FALSE(dict.HasKey("this.is.expanded")); - EXPECT_TRUE(dict.HasKey("this")); + EXPECT_FALSE(dict.FindKey("this.is.expanded")); + EXPECT_TRUE(dict.FindKey("this")); Value* value1; EXPECT_TRUE(dict.Get("this", &value1)); DictionaryValue* value2; @@ -1567,7 +1567,7 @@ EXPECT_EQ(value1, value2); EXPECT_EQ(1U, value2->DictSize()); - EXPECT_TRUE(dict.HasKey("this.isnt.expanded")); + EXPECT_TRUE(dict.FindKey("this.isnt.expanded")); Value* value3; EXPECT_FALSE(dict.Get("this.isnt.expanded", &value3)); Value* value4 = dict.FindKey("this.isnt.expanded"); @@ -1591,8 +1591,6 @@ storage.emplace_back(0); storage.emplace_back(1); Value* list_weak = original_dict.SetKey("list", Value(std::move(storage))); - Value* list_element_0_weak = &list_weak->GetListDeprecated()[0]; - Value* list_element_1_weak = &list_weak->GetListDeprecated()[1]; Value* dict_weak = original_dict.SetKey( "dictionary", base::Value(base::Value::Type::DICTIONARY)); @@ -1661,20 +1659,6 @@ ASSERT_TRUE(copy_list); ASSERT_EQ(2U, copy_list->GetListDeprecated().size()); - Value* copy_list_element_0; - ASSERT_TRUE(copy_list->Get(0, ©_list_element_0)); - ASSERT_TRUE(copy_list_element_0); - ASSERT_NE(copy_list_element_0, list_element_0_weak); - ASSERT_TRUE(copy_list_element_0->is_int()); - ASSERT_EQ(0, copy_list_element_0->GetInt()); - - Value* copy_list_element_1; - ASSERT_TRUE(copy_list->Get(1, ©_list_element_1)); - ASSERT_TRUE(copy_list_element_1); - ASSERT_NE(copy_list_element_1, list_element_1_weak); - ASSERT_TRUE(copy_list_element_1->is_int()); - ASSERT_EQ(1, copy_list_element_1->GetInt()); - copy_value = nullptr; ASSERT_TRUE(copy_dict->Get("dictionary", ©_value)); ASSERT_TRUE(copy_value); @@ -1683,7 +1667,7 @@ DictionaryValue* copy_nested_dictionary = nullptr; ASSERT_TRUE(copy_value->GetAsDictionary(©_nested_dictionary)); ASSERT_TRUE(copy_nested_dictionary); - EXPECT_TRUE(copy_nested_dictionary->HasKey("key")); + EXPECT_TRUE(copy_nested_dictionary->FindKey("key")); } TEST(ValuesTest, Equals) { @@ -2253,15 +2237,6 @@ EXPECT_TRUE(main_dict.GetListWithoutPathExpansion("list", nullptr)); EXPECT_FALSE(main_dict.GetListWithoutPathExpansion("DNE", nullptr)); - EXPECT_TRUE(main_list.Get(0, nullptr)); - EXPECT_TRUE(main_list.Get(1, nullptr)); - EXPECT_TRUE(main_list.Get(2, nullptr)); - EXPECT_TRUE(main_list.Get(3, nullptr)); - EXPECT_TRUE(main_list.Get(4, nullptr)); - EXPECT_TRUE(main_list.Get(5, nullptr)); - EXPECT_TRUE(main_list.Get(6, nullptr)); - EXPECT_FALSE(main_list.Get(7, nullptr)); - EXPECT_FALSE(main_list.GetDictionary(0, nullptr)); EXPECT_FALSE(main_list.GetDictionary(1, nullptr)); EXPECT_FALSE(main_list.GetDictionary(2, nullptr));
diff --git a/build/config/android/internal_rules.gni b/build/config/android/internal_rules.gni index 1f4bc9de..41369b8 100644 --- a/build/config/android/internal_rules.gni +++ b/build/config/android/internal_rules.gni
@@ -893,14 +893,18 @@ "@WrappedPath(@FileArg($_rebased_build_config:deps_info:apk_path))", ] } - if (defined(invoker.proguard_mapping_path) && !_incremental_apk) { - data += [ invoker.proguard_mapping_path ] - _rebased_mapping_path = - rebase_path(invoker.proguard_mapping_path, root_build_dir) - executable_args += [ - "--proguard-mapping-path", - "@WrappedPath($_rebased_mapping_path)", - ] + if (defined(invoker.proguard_mapping_path)) { + if (_incremental_apk) { + not_needed(invoker, [ "proguard_mapping_path" ]) + } else { + data += [ invoker.proguard_mapping_path ] + _rebased_mapping_path = + rebase_path(invoker.proguard_mapping_path, root_build_dir) + executable_args += [ + "--proguard-mapping-path", + "@WrappedPath($_rebased_mapping_path)", + ] + } } if (use_jacoco_coverage) { # Set a default coverage output directory (can be overridden by user
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn index 1093722..b3d4c6b 100644 --- a/build/config/compiler/BUILD.gn +++ b/build/config/compiler/BUILD.gn
@@ -129,7 +129,7 @@ # TODO(gbiv): We disable optimizations by default on most platforms because # the space overhead is too great. We should use some mixture of profiles and # optimization settings to better tune the size increase. - thin_lto_enable_optimizations = (is_chromeos_ash || is_android || is_win || + thin_lto_enable_optimizations = (is_chromeos || is_android || is_win || is_linux || is_mac) && is_official_build # Initialize all local variables with a pattern. This flag will fill @@ -704,7 +704,7 @@ ldflags += [ "-Wl,--thinlto-cache-policy=$cache_policy" ] - if (is_chromeos_ash) { + if (is_chromeos) { # Not much performance difference was noted between the default (100) # and these. ARM was originally set lower than x86 to keep the size # bloat of ThinLTO to <10%, but that's potentially no longer true.
diff --git a/build/config/sanitizers/sanitizers.gni b/build/config/sanitizers/sanitizers.gni index 2940bfc3..ded87a5 100644 --- a/build/config/sanitizers/sanitizers.gni +++ b/build/config/sanitizers/sanitizers.gni
@@ -50,23 +50,15 @@ # See http://clang.llvm.org/docs/ControlFlowIntegrity.html # # TODO(pcc): Remove this flag if/when CFI is enabled in all official builds. - # - # Disable this on linux-chromeos to avoid using ThinLTO there; - # crbug.com/1033839. Similarly, don't use this on ARC builds. - # - # TODO(crbug.com/1159424): Reassess the validity of the next expression. - is_cfi = - is_official_build && is_clang && - (((target_os == "linux" || is_chromeos_lacros) && target_cpu == "x64") || - ((is_chromeos_ash || is_chromeos_lacros) && is_chromeos_device)) + is_cfi = is_official_build && is_clang && + ((target_os == "linux" && target_cpu == "x64") || + (is_chromeos && is_chromeos_device)) # Enable checks for indirect function calls via a function pointer. # TODO(pcc): remove this when we're ready to add these checks by default. # https://crbug.com/701919 - # - # TODO(crbug.com/1159424): Reassess the validity of the next expression. - use_cfi_icall = (target_os == "linux" || is_chromeos_lacros) && - target_cpu == "x64" && is_official_build + use_cfi_icall = + target_os == "linux" && target_cpu == "x64" && is_official_build # Print detailed diagnostics when Control Flow Integrity detects a violation. use_cfi_diag = false
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index 4ca057e..fd375c6 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -7.20220207.1.1 +7.20220207.3.1
diff --git a/build/fuchsia/linux_internal.sdk.sha1 b/build/fuchsia/linux_internal.sdk.sha1 index c98995e4..fd375c6 100644 --- a/build/fuchsia/linux_internal.sdk.sha1 +++ b/build/fuchsia/linux_internal.sdk.sha1
@@ -1 +1 @@ -7.20220207.2.1 +7.20220207.3.1
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 4ca057e..fd375c6 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -7.20220207.1.1 +7.20220207.3.1
diff --git a/cc/animation/animation.h b/cc/animation/animation.h index 6e1a6bf1..bc322cc 100644 --- a/cc/animation/animation.h +++ b/cc/animation/animation.h
@@ -59,7 +59,7 @@ } const KeyframeEffect* keyframe_effect() const { - return keyframe_effect_.Read(*this).get(); + return keyframe_effect_.Read(*this); } // Parent AnimationHost. Animation can be detached from AnimationTimeline.
diff --git a/cc/base/protected_sequence_synchronizer.h b/cc/base/protected_sequence_synchronizer.h index 48a3e96..a936d68 100644 --- a/cc/base/protected_sequence_synchronizer.h +++ b/cc/base/protected_sequence_synchronizer.h
@@ -5,6 +5,7 @@ #ifndef CC_BASE_PROTECTED_SEQUENCE_SYNCHRONIZER_H_ #define CC_BASE_PROTECTED_SEQUENCE_SYNCHRONIZER_H_ +#include <memory> #include <utility> namespace cc { @@ -134,6 +135,87 @@ T value_; }; +// Type specializations for various containers. + +template <typename T> +class ProtectedSequenceForbidden<std::unique_ptr<T>> { + public: + template <typename... Args> + explicit ProtectedSequenceForbidden(Args&&... args) + : value_(std::forward<Args>(args)...) {} + + ProtectedSequenceForbidden(const ProtectedSequenceForbidden&) = delete; + ProtectedSequenceForbidden& operator=(const ProtectedSequenceForbidden&) = + delete; + + const T* Read(const ProtectedSequenceSynchronizer& synchronizer) const { + DCHECK(synchronizer.IsOwnerThread()); + return value_.get(); + } + + std::unique_ptr<T>& Write(const ProtectedSequenceSynchronizer& synchronizer) { + DCHECK(synchronizer.IsOwnerThread()); + return value_; + } + + private: + std::unique_ptr<T> value_; +}; + +template <typename T> +class ProtectedSequenceReadable<std::unique_ptr<T>> { + public: + template <typename... Args> + explicit ProtectedSequenceReadable(Args&&... args) + : value_(std::forward<Args>(args)...) {} + + ProtectedSequenceReadable(const ProtectedSequenceReadable&) = delete; + ProtectedSequenceReadable& operator=(const ProtectedSequenceReadable&) = + delete; + + const T* Read(const ProtectedSequenceSynchronizer& synchronizer) const { + return value_.get(); + } + + std::unique_ptr<T>& Write(const ProtectedSequenceSynchronizer& synchronizer) { + DCHECK(synchronizer.IsOwnerThread()); + synchronizer.WaitForProtectedSequenceCompletion(); + return value_; + } + + private: + std::unique_ptr<T> value_; +}; + +template <typename T> +class ProtectedSequenceWritable<std::unique_ptr<T>> { + public: + template <typename... Args> + explicit ProtectedSequenceWritable(Args&&... args) + : value_(std::forward<Args>(args)...) {} + + ProtectedSequenceWritable(const ProtectedSequenceWritable&) = delete; + ProtectedSequenceWritable& operator=(const ProtectedSequenceWritable&) = + delete; + + const T* Read(const ProtectedSequenceSynchronizer& synchronizer) const { + DCHECK(synchronizer.IsOwnerThread() || synchronizer.InProtectedSequence()); + if (synchronizer.IsOwnerThread()) + synchronizer.WaitForProtectedSequenceCompletion(); + return value_.get(); + } + + std::unique_ptr<T>& Write(const ProtectedSequenceSynchronizer& synchronizer) { + DCHECK(synchronizer.IsOwnerThread() || synchronizer.InProtectedSequence()); + if (synchronizer.IsOwnerThread()) + synchronizer.WaitForProtectedSequenceCompletion(); + return value_; + } + + private: + std::unique_ptr<T> value_; +}; + } // namespace cc #endif // CC_BASE_PROTECTED_SEQUENCE_SYNCHRONIZER_H_
diff --git a/cc/layers/layer.cc b/cc/layers/layer.cc index dc0ef057..a22deab6 100644 --- a/cc/layers/layer.cc +++ b/cc/layers/layer.cc
@@ -139,7 +139,7 @@ #if DCHECK_IS_ON() const Layer::LayerTreeInputs* Layer::layer_tree_inputs() const { DCHECK(!IsAttached() || !IsUsingLayerLists()); - return layer_tree_inputs_.Read(*this).get(); + return layer_tree_inputs_.Read(*this); } #endif @@ -251,13 +251,24 @@ return nullptr; } -void Layer::SetParent(Layer* layer) { +void Layer::SetParent(Layer* layer, RemovalReason reason) { DCHECK(IsMutationAllowed()); DCHECK(!layer || !layer->HasAncestor(this)); + DCHECK(reason == RemovalReason::kNormal || !layer); raw_ptr<Layer>& parent = parent_.Write(*this); parent = layer; - SetLayerTreeHost(parent ? parent->layer_tree_host() : nullptr); + if (reason == RemovalReason::kForReadd) { + // When passing kForReadd, the caller is responsible for calling + // SetLayerTreeHost. Deferring this until after the readd means that the + // single SetLayerTreeHost call will generally set layer_tree_host_ to the + // same value, and thus be able to optimize away the recursive tree walk. +#if DCHECK_IS_ON() + DCHECK(allow_remove_for_readd_); +#endif + } else { + SetLayerTreeHost(parent ? parent->layer_tree_host() : nullptr); + } SetPropertyTreesNeedRebuild(); } @@ -268,15 +279,16 @@ void Layer::InsertChild(scoped_refptr<Layer> child, size_t index) { DCHECK(IsPropertyChangeAllowed()); - child->RemoveFromParent(); + AllowRemoveForReadd allow(child.get()); + child->RemoveFromParentForReadd(); AddDrawableDescendants(child->NumDescendantsThatDrawContent() + (child->draws_content() ? 1 : 0)); - child->SetParent(this); + child->SetParent(this, RemovalReason::kNormal); child->SetSubtreePropertyChanged(); auto& inputs = inputs_.Write(*this); index = std::min(index, inputs.children.size()); - const auto& layer_tree_inputs = layer_tree_inputs_.Read(*this); + const auto* layer_tree_inputs = layer_tree_inputs_.Read(*this); if (layer_tree_inputs && layer_tree_inputs->mask_layer && index && index == inputs.children.size()) { // Ensure that the mask layer is always the last child. @@ -290,11 +302,17 @@ void Layer::RemoveFromParent() { DCHECK(IsPropertyChangeAllowed()); if (parent_.Read(*this)) - parent_.Write(*this)->RemoveChild(this); + parent_.Write(*this)->RemoveChild(this, RemovalReason::kNormal); } -void Layer::RemoveChild(Layer* child) { - const auto& layer_tree_inputs = layer_tree_inputs_.Read(*this); +void Layer::RemoveFromParentForReadd() { + DCHECK(IsPropertyChangeAllowed()); + if (parent_.Read(*this)) + parent_.Write(*this)->RemoveChild(this, RemovalReason::kForReadd); +} + +void Layer::RemoveChild(Layer* child, RemovalReason reason) { + const auto* layer_tree_inputs = layer_tree_inputs_.Read(*this); if (layer_tree_inputs && child == layer_tree_inputs->mask_layer) layer_tree_inputs_.Write(*this)->mask_layer = nullptr; @@ -304,7 +322,7 @@ if (iter->get() != child) continue; - child->SetParent(nullptr); + child->SetParent(nullptr, reason); AddDrawableDescendants(-child->NumDescendantsThatDrawContent() - (child->draws_content() ? 1 : 0)); inputs.children.erase(iter); @@ -378,7 +396,6 @@ reference->RemoveFromParent(); if (new_layer.get()) { - new_layer->RemoveFromParent(); InsertChild(new_layer, reference_index); } } @@ -452,7 +469,7 @@ for (auto& new_child : new_children) children_to_remove.erase(new_child.get()); for (auto* child : children_to_remove) { - child->SetParent(nullptr); + child->SetParent(nullptr, RemovalReason::kNormal); AddDrawableDescendants(-child->NumDescendantsThatDrawContent() - (child->draws_content() ? 1 : 0)); } @@ -474,10 +491,11 @@ // |child->parent()| such as the above loop. for (auto& child : new_children) { if (child->parent() != this) { - child->RemoveFromParent(); + AllowRemoveForReadd allow(child.get()); + child->RemoveFromParentForReadd(); AddDrawableDescendants(child->NumDescendantsThatDrawContent() + (child->draws_content() ? 1 : 0)); - child->SetParent(this); + child->SetParent(this, RemovalReason::kNormal); child->SetSubtreePropertyChanged(); } } @@ -1363,7 +1381,7 @@ } std::string Layer::DebugName() const { - const auto& info = debug_info_.Read(*this); + const auto* info = debug_info_.Read(*this); return info ? info->name : ""; } @@ -1479,7 +1497,7 @@ layer->SetNeedsPushProperties(); // debug_info_->invalidations, if exist, will be cleared in the function. - layer->UpdateDebugInfo(debug_info_.Read(*this).get()); + layer->UpdateDebugInfo(debug_info_.Write(*this).get()); if (inputs.rare_inputs) { layer->SetNonFastScrollableRegion(
diff --git a/cc/layers/layer.h b/cc/layers/layer.h index a631d0a..7c16202c 100644 --- a/cc/layers/layer.h +++ b/cc/layers/layer.h
@@ -677,9 +677,7 @@ // display. virtual sk_sp<const SkPicture> GetPicture() const; - const LayerDebugInfo* debug_info() const { - return debug_info_.Read(*this).get(); - } + const LayerDebugInfo* debug_info() const { return debug_info_.Read(*this); } LayerDebugInfo& EnsureDebugInfo(); void ClearDebugInfo(); @@ -889,7 +887,7 @@ const LayerTreeInputs* layer_tree_inputs() const; #else const LayerTreeInputs* layer_tree_inputs() const { - return layer_tree_inputs_.Read(*this).get(); + return layer_tree_inputs_.Read(*this); } #endif @@ -902,10 +900,23 @@ void AddClipChild(Layer* child); void RemoveClipChild(Layer* child); - void SetParent(Layer* layer); + // For functions that do or (as SetParent) might remove a child layer, + // passing kForReadd causes the removal to *not* call SetLayerTreeHost. + // This variation assumes that the caller will re-add the layer (probably to + // the same layer tree host) and then call SetLayerTreeHost. + enum class RemovalReason { + kNormal, + kForReadd, + }; + + void SetParent(Layer* layer, RemovalReason reason); // This should only be called from RemoveFromParent(). - void RemoveChild(Layer* child); + void RemoveChild(Layer* child, RemovalReason reason); + + // Variant (for internal use) of RemoveFromParent (which is a widely-used + // public API) as though it were passed RemovalReason::kForReadd. + void RemoveFromParentForReadd(); bool GetBitFlag(uint8_t mask) const; @@ -1104,6 +1115,43 @@ ProtectedSequenceWritable<bool> subtree_property_changed_; +#if DCHECK_IS_ON() + class AllowRemoveForReadd { + public: + explicit AllowRemoveForReadd(Layer* layer) : layer_(layer) { + // Assume these will never be nested. If this DCHECK() fails due to + // nesting, we could convert to using base::AutoReset. + DCHECK(!layer_->allow_remove_for_readd_); + layer_->allow_remove_for_readd_ = true; + } + ~AllowRemoveForReadd() { + // Check that the layer has actually been re-added. + DCHECK(layer_->parent()); + + // Assume these will never be nested. If this DCHECK() fails due to + // nesting, we could convert to using base::AutoReset. + DCHECK(layer_->allow_remove_for_readd_); + layer_->allow_remove_for_readd_ = false; + } + + AllowRemoveForReadd(const AllowRemoveForReadd&) = delete; + AllowRemoveForReadd& operator=(const AllowRemoveForReadd&) = delete; + + private: + Layer* layer_; + }; + + bool allow_remove_for_readd_ = false; +#else + class AllowRemoveForReadd { + public: + explicit AllowRemoveForReadd(Layer* layer) {} + + AllowRemoveForReadd(const AllowRemoveForReadd&) = delete; + AllowRemoveForReadd& operator=(const AllowRemoveForReadd&) = delete; + }; +#endif + ProtectedSequenceWritable<std::unique_ptr<LayerDebugInfo>> debug_info_; static constexpr gfx::Transform kIdentityTransform{};
diff --git a/cc/layers/painted_overlay_scrollbar_layer.cc b/cc/layers/painted_overlay_scrollbar_layer.cc index ad08e35d..33ff15f 100644 --- a/cc/layers/painted_overlay_scrollbar_layer.cc +++ b/cc/layers/painted_overlay_scrollbar_layer.cc
@@ -84,7 +84,7 @@ scrollbar_layer->SetTrackLength(track_rect_.Read(*this).height()); } - if (thumb_resource_.Read(*this).get()) { + if (thumb_resource_.Read(*this)) { auto iter = commit_state.ui_resource_sizes.find(thumb_resource_.Read(*this)->id()); gfx::Size image_bounds = (iter == commit_state.ui_resource_sizes.end()) @@ -100,7 +100,7 @@ scrollbar_layer->set_thumb_ui_resource_id(0); } - if (track_resource_.Read(*this).get()) + if (track_resource_.Read(*this)) scrollbar_layer->set_track_ui_resource_id( track_resource_.Read(*this)->id()); else
diff --git a/cc/layers/painted_scrollbar_layer.cc b/cc/layers/painted_scrollbar_layer.cc index ee0943f..3250444 100644 --- a/cc/layers/painted_scrollbar_layer.cc +++ b/cc/layers/painted_scrollbar_layer.cc
@@ -82,16 +82,18 @@ scrollbar_layer->SetThumbLength(thumb_size_.Read(*this).height()); } - if (track_resource_.Read(*this).get()) + if (track_resource_.Read(*this)) { scrollbar_layer->set_track_ui_resource_id( track_resource_.Read(*this)->id()); - else + } else { scrollbar_layer->set_track_ui_resource_id(0); - if (thumb_resource_.Read(*this).get()) + } + if (thumb_resource_.Read(*this)) { scrollbar_layer->set_thumb_ui_resource_id( thumb_resource_.Read(*this)->id()); - else + } else { scrollbar_layer->set_thumb_ui_resource_id(0); + } scrollbar_layer->SetScrollbarPaintedOpacity(painted_opacity_.Read(*this));
diff --git a/cc/layers/painted_scrollbar_layer.h b/cc/layers/painted_scrollbar_layer.h index a055291..3983859 100644 --- a/cc/layers/painted_scrollbar_layer.h +++ b/cc/layers/painted_scrollbar_layer.h
@@ -52,12 +52,12 @@ // For unit tests UIResourceId track_resource_id() { - if (const auto& track_resource = track_resource_.Read(*this)) + if (const auto* track_resource = track_resource_.Read(*this)) return track_resource->id(); return 0; } UIResourceId thumb_resource_id() { - if (const auto& thumb_resource = thumb_resource_.Read(*this)) + if (const auto* thumb_resource = thumb_resource_.Read(*this)) return thumb_resource->id(); return 0; }
diff --git a/cc/layers/picture_layer.h b/cc/layers/picture_layer.h index 0a4fabe8..1093e53 100644 --- a/cc/layers/picture_layer.h +++ b/cc/layers/picture_layer.h
@@ -55,8 +55,12 @@ ContentLayerClient* client() { return picture_layer_inputs_.client; } - RecordingSource* GetRecordingSourceForTesting() const { - return recording_source_.Read(*this).get(); + RecordingSource* GetRecordingSourceForTesting() { + return recording_source_.Write(*this).get(); + } + + const RecordingSource* GetRecordingSourceForTesting() const { + return recording_source_.Read(*this); } const DisplayItemList* GetDisplayItemList() const;
diff --git a/cc/resources/scoped_ui_resource.h b/cc/resources/scoped_ui_resource.h index 9452291..716741c 100644 --- a/cc/resources/scoped_ui_resource.h +++ b/cc/resources/scoped_ui_resource.h
@@ -5,6 +5,8 @@ #ifndef CC_RESOURCES_SCOPED_UI_RESOURCE_H_ #define CC_RESOURCES_SCOPED_UI_RESOURCE_H_ +#include <memory> + #include "base/memory/raw_ptr.h" #include "base/memory/ref_counted.h" #include "cc/cc_export.h" @@ -33,7 +35,7 @@ // UIResourceClient implementation. UIResourceBitmap GetBitmap(UIResourceId uid, bool resource_lost) override; - UIResourceId id() { return id_; } + UIResourceId id() const { return id_; } // Returns the memory usage of the bitmap. size_t EstimateMemoryUsage() const { return bitmap_.SizeInBytes(); }
diff --git a/chrome/VERSION b/chrome/VERSION index de30fa8..2173ab1 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=100 MINOR=0 -BUILD=4876 +BUILD=4877 PATCH=0
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn index 44a2fc4..6104a92 100644 --- a/chrome/android/BUILD.gn +++ b/chrome/android/BUILD.gn
@@ -287,6 +287,7 @@ "//chrome/browser/password_manager/android:backend_interface_public_impl_java", "//chrome/browser/password_manager/android:settings_interface_public_impl_java", "//chrome/browser/policy/android:delegate_public_impl_java", + "//chrome/browser/touch_to_fill/android/internal:resource_provider_public_impl_java", "//chrome/browser/ui/android/theme:delegate_public_impl_java", "//components/externalauth/android:google_delegate_public_impl_java", "//components/language/android:ulp_delegate_public_java", @@ -607,6 +608,7 @@ "//third_party/androidx:androidx_lifecycle_lifecycle_common_java", "//third_party/androidx:androidx_lifecycle_lifecycle_common_java8_java", "//third_party/androidx:androidx_lifecycle_lifecycle_runtime_java", + "//third_party/androidx:androidx_localbroadcastmanager_localbroadcastmanager_java", "//third_party/androidx:androidx_mediarouter_mediarouter_java", "//third_party/androidx:androidx_preference_preference_java", "//third_party/androidx:androidx_recyclerview_recyclerview_java", @@ -1134,10 +1136,12 @@ "//third_party/android_deps:protobuf_lite_runtime_java", "//third_party/android_support_test_runner:rules_java", "//third_party/android_support_test_runner:runner_java", + "//third_party/androidx:androidx_activity_activity_java", "//third_party/androidx:androidx_annotation_annotation_java", "//third_party/androidx:androidx_browser_browser_java", "//third_party/androidx:androidx_collection_collection_java", "//third_party/androidx:androidx_lifecycle_lifecycle_common_java", + "//third_party/androidx:androidx_lifecycle_lifecycle_runtime_java", "//third_party/androidx:androidx_mediarouter_mediarouter_java", "//third_party/androidx:androidx_recyclerview_recyclerview_java", "//third_party/androidx:androidx_swiperefreshlayout_swiperefreshlayout_java", @@ -1556,6 +1560,7 @@ "//components/webauthn/android:java", "//components/webauthn/android:test_support_java", "//content/public/android:content_java", + "//content/public/common:common_java", "//content/public/test/android:content_java_test_support", "//media/base/android:java_switches", "//media/base/android:media_java",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni index a4ad9f0..f45de42c 100644 --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni
@@ -10,6 +10,7 @@ "java/src/org/chromium/chrome/browser/AppHooksModule.java", "java/src/org/chromium/chrome/browser/AppIndexingUtil.java", "java/src/org/chromium/chrome/browser/ApplicationLifetime.java", + "java/src/org/chromium/chrome/browser/BackPressHelper.java", "java/src/org/chromium/chrome/browser/BrowserRestartActivity.java", "java/src/org/chromium/chrome/browser/ChromeAccessorActivity.java", "java/src/org/chromium/chrome/browser/ChromeActionModeHandler.java", @@ -349,6 +350,7 @@ "java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java", "java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java", "java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutTab.java", + "java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripScrim.java", "java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripStacker.java", "java/src/org/chromium/chrome/browser/compositor/overlays/strip/TabLoadTracker.java", "java/src/org/chromium/chrome/browser/compositor/resources/StaticResourcePreloads.java", @@ -462,6 +464,7 @@ "java/src/org/chromium/chrome/browser/customtabs/CustomTabsClientFileProcessor.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnection.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabsConnectionServiceImpl.java", + "java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java", "java/src/org/chromium/chrome/browser/customtabs/CustomTabsShareBroadcastReceiver.java", "java/src/org/chromium/chrome/browser/customtabs/DefaultBrowserProviderImpl.java", "java/src/org/chromium/chrome/browser/customtabs/FirstMeaningfulPaintObserver.java",
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni index baf0130d..d05909c 100644 --- a/chrome/android/chrome_junit_test_java_sources.gni +++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -1,5 +1,6 @@ chrome_junit_test_java_sources = [ "junit/src/org/chromium/chrome/browser/AppIndexingUtilTest.java", + "junit/src/org/chromium/chrome/browser/BackPressHelperUnitTest.java", "junit/src/org/chromium/chrome/browser/ChromeActionModeHandlerUnitTest.java", "junit/src/org/chromium/chrome/browser/ChromeActivityUnitTest.java", "junit/src/org/chromium/chrome/browser/ChromeBackupAgentTest.java", @@ -178,6 +179,7 @@ "junit/src/org/chromium/chrome/browser/password_manager/settings/TimedCallbackDelayerTest.java", "junit/src/org/chromium/chrome/browser/privacy/settings/PrivacyPreferencesManagerImplTest.java", "junit/src/org/chromium/chrome/browser/quickactionsearchwidget/QuickActionSearchWidgetProviderTest.java", + "junit/src/org/chromium/chrome/browser/read_later/ReadLaterIPHControllerUnitTest.java", "junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java", "junit/src/org/chromium/chrome/browser/reengagement/ReengagementNotificationControllerTest.java", "junit/src/org/chromium/chrome/browser/safe_browsing/SafeBrowsingReferringAppBridgeTest.java",
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index 8311e72..1e68675 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -52,6 +52,7 @@ "javatests/src/org/chromium/chrome/browser/WarmupManagerTest.java", "javatests/src/org/chromium/chrome/browser/accessibility/FontSizePrefsTest.java", "javatests/src/org/chromium/chrome/browser/accessibility/settings/AccessibilitySettingsTest.java", + "javatests/src/org/chromium/chrome/browser/app/ContextMenuDragTest.java", "javatests/src/org/chromium/chrome/browser/app/appmenu/OverviewAppMenuTest.java", "javatests/src/org/chromium/chrome/browser/app/appmenu/TabbedAppMenuTest.java", "javatests/src/org/chromium/chrome/browser/app/metrics/LaunchCauseMetricsTest.java",
diff --git a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java index 1a2457c..531e1492 100644 --- a/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java +++ b/chrome/android/features/vr/java/src/org/chromium/chrome/browser/vr/VrShellDelegate.java
@@ -699,7 +699,7 @@ // a thread-safety issue since it thinks the receiver isn't fully initialized before being // exposed to other threads. This isn't actually an issue in this case, but we need to set // sVrBroadcastReceiver after we're done using it here to fix the compile error. - activity.registerReceiver(receiver, filter); + ContextUtils.registerNonExportedBroadcastReceiver(activity, receiver, filter); sVrBroadcastReceiver = receiver; Intent vrIntent = new Intent(VR_ENTRY_RESULT_ACTION); vrIntent.setPackage(activity.getPackageName());
diff --git a/chrome/android/java/res/drawable/distilled_page_prefs_button_bg.xml b/chrome/android/java/res/drawable/distilled_page_prefs_button_bg.xml index e3ea906d..71820fc 100644 --- a/chrome/android/java/res/drawable/distilled_page_prefs_button_bg.xml +++ b/chrome/android/java/res/drawable/distilled_page_prefs_button_bg.xml
@@ -7,9 +7,12 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item - android:drawable="@color/distilled_page_prefs_selected" - android:state_checked="true" /> + <item android:state_checked="true"> + <shape android:shape="rectangle"> + <solid android:color="@color/distilled_page_prefs_selected"/> + <corners android:radius="16dp"/> + </shape> + </item> <item android:drawable="@color/distilled_page_prefs_unselected" android:state_checked="false" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/BackPressHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/BackPressHelper.java new file mode 100644 index 0000000..f301843 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/BackPressHelper.java
@@ -0,0 +1,63 @@ +// Copyright 2022 The Chromium 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; + +import androidx.activity.OnBackPressedCallback; +import androidx.activity.OnBackPressedDispatcher; +import androidx.lifecycle.LifecycleOwner; + +/** + * Helper class for back press event handling via {@link OnBackPressedDisptacher}. This is + * a recommended way over {@link Activity#onBackPressed}. Refer to the Android developer's guide + * {@link https://developer.android.com/guide/navigation/navigation-custom-back}. + */ +public final class BackPressHelper { + /** + * Handles back press event. + */ + public interface BackPressedHandler { + /** + * @return {@code true} if the event was consumed. {@code false} otherwise. + */ + boolean onBackPressed(); + } + + /** + * Create a {@link BackPressHelper} that can handle a chain of handlers. + * @param lifecycleOwner {@link LifecycleOwner} managing the back press logic's lifecycle. + * @param dispatcher {@link OnBackPressedDispatcher} that holds other callbacks. + * @param handler {@link BackPressedHandler} implementing the caller's back press handler. + */ + public static void create(LifecycleOwner lifecycleOwner, OnBackPressedDispatcher dispatcher, + BackPressedHandler handler) { + new BackPressHelper(lifecycleOwner, dispatcher, handler); + } + + /** + * Let the back press event be processed by next {@link OnBackPressedCallback}. A callback + * needs to be in enabled state only when it plans to handle back press event. If the callback + * cannot handle it for whatever reason, it can call this method to give the next callback + * or a fallback runnable an opportunity to process it. If the callback needs to receive + * back press events in the future again, it should enable itself after this call. + * @param dispatcher {@link OnBackPressedDispatcher} holding other callbacks. + * @param callback {@link OnBackkPressedCallback} which just received the event but ended up + * not handling it. + */ + public static void onBackPressed( + OnBackPressedDispatcher dispatcher, OnBackPressedCallback callback) { + callback.setEnabled(false); + dispatcher.onBackPressed(); + } + + private BackPressHelper(LifecycleOwner lifecycleOwner, OnBackPressedDispatcher dispatcher, + BackPressedHandler handler) { + dispatcher.addCallback(lifecycleOwner, new OnBackPressedCallback(true) { + @Override + public void handleOnBackPressed() { + if (!handler.onBackPressed()) onBackPressed(dispatcher, this); + } + }); + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java index 1f5a74a..2b1935e 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -2531,7 +2531,8 @@ } if (id == R.id.delete_from_reading_list_menu_id) { - ReadingListUtils.deleteFromReadingList(mSnackbarManager, /*activity=*/this, currentTab); + ReadingListUtils.deleteFromReadingList( + new BookmarkModel(), mSnackbarManager, /*activity=*/this, currentTab); RecordUserAction.record("MobileMenuDeleteFromReadingList"); return true; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/video_tutorials/VideoPlayerActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/video_tutorials/VideoPlayerActivity.java index fec821a1..67677d3 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/app/video_tutorials/VideoPlayerActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/app/video_tutorials/VideoPlayerActivity.java
@@ -12,6 +12,7 @@ import android.view.WindowManager; import org.chromium.base.IntentUtils; +import org.chromium.chrome.browser.BackPressHelper; import org.chromium.chrome.browser.ChromeTabbedActivity; import org.chromium.chrome.browser.SynchronousInitializationActivity; import org.chromium.chrome.browser.WebContentsFactory; @@ -58,6 +59,7 @@ int featureType = IntentUtils.safeGetIntExtra(getIntent(), EXTRA_VIDEO_TUTORIAL, FeatureType.INVALID); videoTutorialService.getTutorial(featureType, mCoordinator::playVideoTutorial); + BackPressHelper.create(this, getOnBackPressedDispatcher(), mCoordinator::onBackPressed); } private Pair<WebContents, ContentView> createWebContents() { @@ -72,12 +74,6 @@ } @Override - public void onBackPressed() { - if (mCoordinator.onBackPressed()) return; - super.onBackPressed(); - } - - @Override protected void onDestroy() { mCoordinator.destroy(); super.onDestroy();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/base/DexFixer.java b/chrome/android/java/src/org/chromium/chrome/browser/base/DexFixer.java index 46138ea8..4283535 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/base/DexFixer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/base/DexFixer.java
@@ -20,7 +20,6 @@ import org.chromium.base.Log; import org.chromium.base.compat.ApiHelperForM; import org.chromium.base.compat.ApiHelperForO; -import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.task.PostTask; import org.chromium.base.task.TaskTraits; import org.chromium.build.BuildConfig; @@ -71,7 +70,8 @@ @WorkerThread @VisibleForTesting - static void fixDexIfNecessary(Runtime runtime) { + @DexFixerReason + static int fixDexIfNecessary(Runtime runtime) { ApplicationInfo appInfo = ContextUtils.getApplicationContext().getApplicationInfo(); @DexFixerReason int reason = needsDexCompile(appInfo); @@ -87,10 +87,10 @@ cmd += ContextUtils.getApplicationContext().getPackageName(); runtime.exec(cmd); } catch (IOException e) { - reason = DexFixerReason.FAILED_TO_RUN; + // Don't crash. } } - RecordHistogram.recordEnumeratedHistogram("Android.DexFixer", reason, DexFixerReason.COUNT); + return reason; } private static boolean shouldSkipDexFix() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java index f55c265..4b1e8ad 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/bookmarks/BookmarkActivity.java
@@ -11,6 +11,7 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.IntentUtils; +import org.chromium.chrome.browser.BackPressHelper; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.SnackbarActivity; import org.chromium.components.bookmarks.BookmarkId; @@ -40,6 +41,7 @@ if (TextUtils.isEmpty(url)) url = UrlConstants.BOOKMARKS_URL; mBookmarkManager.updateForUrl(url); setContentView(mBookmarkManager.getView()); + BackPressHelper.create(this, getOnBackPressedDispatcher(), mBookmarkManager::onBackPressed); } @Override @@ -49,11 +51,6 @@ } @Override - public void onBackPressed() { - if (!mBookmarkManager.onBackPressed()) super.onBackPressed(); - } - - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == EDIT_BOOKMARK_REQUEST_CODE && resultCode == RESULT_OK) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java index d1fedaca..3db7f9c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/LayoutManagerChromeTablet.java
@@ -21,6 +21,7 @@ import org.chromium.chrome.browser.theme.TopUiThemeColorProvider; import org.chromium.chrome.browser.toolbar.ControlContainer; import org.chromium.chrome.features.start_surface.StartSurface; +import org.chromium.chrome.features.start_surface.StartSurface.Controller; import org.chromium.ui.resources.dynamics.DynamicResourceLoader; /** @@ -28,7 +29,7 @@ * the tablet. */ public class LayoutManagerChromeTablet extends LayoutManagerChrome { - + private Controller mStartSurfaceController; private StripLayoutHelperManager mTabStripLayoutHelperManager; // Internal State @@ -59,6 +60,14 @@ host.getContext(), this, mHost.getLayoutRenderHost(), () -> mLayerTitleCache); addSceneOverlay(mTabStripLayoutHelperManager); + if (startSurface != null) { + mStartSurfaceController = startSurface.getController(); + if (mStartSurfaceController != null) { + mStartSurfaceController.addOverviewModeObserver( + mTabStripLayoutHelperManager.getStartSurfaceObserver()); + } + } + setNextLayout(null); } @@ -71,6 +80,11 @@ mLayerTitleCache = null; } + if (mStartSurfaceController != null && mTabStripLayoutHelperManager != null) { + mStartSurfaceController.removeOverviewModeObserver( + mTabStripLayoutHelperManager.getStartSurfaceObserver()); + } + if (mTabStripLayoutHelperManager != null) { mTabStripLayoutHelperManager.destroy(); mTabStripLayoutHelperManager = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java index fbbec30..c077ef8a 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelper.java
@@ -113,7 +113,6 @@ private final StripTabEventHandler mStripTabEventHandler = new StripTabEventHandler(); private final TabLoadTrackerCallback mTabLoadTrackerHost = new TabLoadTrackerCallbackImpl(); private Animator mRunningAnimator; - private final CompositorButton mNewTabButton; // Layout Constants @@ -157,6 +156,7 @@ public static final int ID_CLOSE_ALL_TABS = 0; private Context mContext; + /** * Creates an instance of the {@link StripLayoutHelper}. * @param context The current Android {@link Context}.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java index 5949e005..28b2379 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
@@ -4,6 +4,7 @@ package org.chromium.chrome.browser.compositor.overlays.strip; +import android.animation.ValueAnimator; import android.content.Context; import android.content.res.Resources; import android.graphics.Bitmap; @@ -24,6 +25,8 @@ import org.chromium.chrome.browser.compositor.layouts.eventfilter.AreaGestureEventFilter; import org.chromium.chrome.browser.compositor.layouts.eventfilter.GestureHandler; import org.chromium.chrome.browser.compositor.scene_layer.TabStripSceneLayer; +import org.chromium.chrome.browser.flags.CachedFeatureFlags; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.layouts.EventFilter; import org.chromium.chrome.browser.layouts.SceneOverlay; import org.chromium.chrome.browser.layouts.components.VirtualView; @@ -39,6 +42,8 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelectorObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabModelObserver; import org.chromium.chrome.browser.tabmodel.TabModelSelectorTabObserver; +import org.chromium.chrome.features.start_surface.StartSurface; +import org.chromium.components.browser_ui.widget.animation.Interpolators; import org.chromium.ui.base.LocalizationUtils; import org.chromium.ui.resources.ResourceManager; import org.chromium.url.GURL; @@ -50,6 +55,7 @@ * all input and model events to the proper destination. */ public class StripLayoutHelperManager implements SceneOverlay { + private static final long FADE_SCRIM_DURATION_MS = 500; // Caching Variables private final RectF mStripFilterArea = new RectF(); @@ -78,9 +84,13 @@ private int mOrientation; private final CompositorButton mModelSelectorButton; + private final StripScrim mStripScrim; + private ValueAnimator mScrimFadeAnimation; + private TabStripSceneLayer mTabStripTreeProvider; private TabStripEventHandler mTabStripEventHandler; + private StartSurfaceOverviewObserver mStartSurfaceOverviewObserver; private TabModelSelectorTabModelObserver mTabModelSelectorTabModelObserver; private TabModelSelectorTabObserver mTabModelSelectorTabObserver; @@ -101,6 +111,7 @@ @Override public void onDown(float x, float y, boolean fromMouse, int buttons) { if (mModelSelectorButton.onDown(x, y)) return; + if (mStripScrim.isVisible()) return; getActiveStripLayoutHelper().onDown(time(), x, y, fromMouse, buttons); } @@ -112,12 +123,14 @@ mTabModelSelector.selectModel(!mTabModelSelector.isIncognitoSelected()); return; } + if (mStripScrim.isVisible()) return; getActiveStripLayoutHelper().onUpOrCancel(time()); } @Override public void drag(float x, float y, float dx, float dy, float tx, float ty) { mModelSelectorButton.drag(x, y); + if (mStripScrim.isVisible()) return; getActiveStripLayoutHelper().drag(time(), x, y, dx, dy, tx, ty); } @@ -128,16 +141,19 @@ mModelSelectorButton.handleClick(time); return; } + if (mStripScrim.isVisible()) return; getActiveStripLayoutHelper().click(time(), x, y, fromMouse, buttons); } @Override public void fling(float x, float y, float velocityX, float velocityY) { + if (mStripScrim.isVisible()) return; getActiveStripLayoutHelper().fling(time(), x, y, velocityX, velocityY); } @Override public void onLongPress(float x, float y) { + if (mStripScrim.isVisible()) return; getActiveStripLayoutHelper().onLongPress(time(), x, y); } @@ -152,6 +168,55 @@ } /** + * Observer for Start Surface overview events. + */ + class StartSurfaceOverviewObserver implements StartSurface.OverviewModeObserver { + @Override + public void startedShowing() { + updateScrimVisibility(true); + } + + @Override + public void finishedShowing() {} + + @Override + public void startedHiding() { + updateScrimVisibility(false); + } + + @Override + public void finishedHiding() {} + + private void updateScrimVisibility(boolean visibility) { + if (!isGridTabSwitcherEnabled()) return; + + if (mScrimFadeAnimation != null) { + mScrimFadeAnimation.cancel(); + } + + float startAlpha = visibility ? 0.f : 1.f; + float endAlpha = visibility ? 1.f : 0.f; + mScrimFadeAnimation = ValueAnimator.ofFloat(startAlpha, endAlpha); + mScrimFadeAnimation.setInterpolator(Interpolators.LINEAR_INTERPOLATOR); + mScrimFadeAnimation.setDuration(FADE_SCRIM_DURATION_MS); + mScrimFadeAnimation.addUpdateListener((anim -> { + final float currentAlpha = (float) anim.getAnimatedValue(); + mStripScrim.setAlpha(currentAlpha); + mTabStripTreeProvider.updateStripScrim(mStripScrim); + })); + mScrimFadeAnimation.start(); + mStripScrim.setVisible(visibility); + } + } + + /** + * @return Returns overview mode observer for start surface. + */ + public StartSurfaceOverviewObserver getStartSurfaceObserver() { + return mStartSurfaceOverviewObserver; + } + + /** * Creates an instance of the {@link StripLayoutHelperManager}. * @param context The current Android {@link Context}. * @param updateHost The parent {@link LayoutUpdateHost}. @@ -165,6 +230,7 @@ mLayerTitleCacheSupplier = layerTitleCacheSupplier; mTabStripTreeProvider = new TabStripSceneLayer(context); mTabStripEventHandler = new TabStripEventHandler(); + mStartSurfaceOverviewObserver = new StartSurfaceOverviewObserver(); mDefaultTitle = context.getString(R.string.tab_loading_default_title); mEventFilter = new AreaGestureEventFilter(context, mTabStripEventHandler, null, false, false); @@ -194,10 +260,20 @@ res.getString(R.string.accessibility_tabstrip_btn_incognito_toggle_standard), res.getString(R.string.accessibility_tabstrip_btn_incognito_toggle_incognito)); + mStripScrim = new StripScrim(mWidth, mHeight); + mStripScrim.setVisible(false); + onContextChanged(context); } /** + * @return Return scrim to be applied on tab strip. + */ + public StripScrim getStripScrim() { + return mStripScrim; + } + + /** * Cleans up internal state. */ public void destroy() { @@ -270,6 +346,8 @@ mModelSelectorButton.setX(MODEL_SELECTOR_BUTTON_END_PADDING_DP); } + updateStripScrim(); + mNormalHelper.onSizeChanged(mWidth, mHeight); mIncognitoHelper.onSizeChanged(mWidth, mHeight); @@ -277,6 +355,27 @@ mEventFilter.setEventArea(mStripFilterArea); } + private void updateStripScrim() { + if (!isGridTabSwitcherEnabled()) return; + // Update width + float scrimWidth = mModelSelectorButton.isVisible() + ? mWidth - getModelSelectorButtonWidthWithPadding() + : mWidth; + mStripScrim.setWidth(scrimWidth); + + // Update drawX + float drawX = 0; + if (LocalizationUtils.isLayoutRtl() && mModelSelectorButton.isVisible()) { + drawX = getModelSelectorButtonWidthWithPadding(); + } + mStripScrim.setX(drawX); + } + + private float getModelSelectorButtonWidthWithPadding() { + return MODEL_SELECTOR_BUTTON_WIDTH_DP + MODEL_SELECTOR_BUTTON_END_PADDING_DP + + MODEL_SELECTOR_BUTTON_START_PADDING_DP; + } + public CompositorButton getNewTabButton() { return getActiveStripLayoutHelper().getNewTabButton(); } @@ -556,16 +655,18 @@ boolean isVisible = mTabModelSelector.getModel(true).getCount() != 0; mModelSelectorButton.setVisible(isVisible); - float endMargin = isVisible - ? MODEL_SELECTOR_BUTTON_WIDTH_DP + MODEL_SELECTOR_BUTTON_END_PADDING_DP - + MODEL_SELECTOR_BUTTON_START_PADDING_DP - : 0.0f; + float endMargin = isVisible ? getModelSelectorButtonWidthWithPadding() : 0.0f; mNormalHelper.setEndMargin(endMargin); mIncognitoHelper.setEndMargin(endMargin); + updateStripScrim(); } } + private boolean isGridTabSwitcherEnabled() { + return CachedFeatureFlags.isEnabled(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS); + } + /** * @param incognito Whether or not you want the incognito StripLayoutHelper * @return The requested StripLayoutHelper.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripScrim.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripScrim.java new file mode 100644 index 0000000..c1fa430 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripScrim.java
@@ -0,0 +1,69 @@ +// Copyright 2022 The Chromium 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.compositor.overlays.strip; + +import org.chromium.chrome.R; +/** + * Tab strip scrim properties. + */ +public class StripScrim { + private float mDrawX; + private float mWidth; + private float mHeight; + private float mAlpha; + private boolean mIsShowing; + + public StripScrim(float width, float height) { + this.mWidth = width; + this.mHeight = height; + } + + public float getX() { + return mDrawX; + } + + public void setX(float mDrawX) { + this.mDrawX = mDrawX; + } + + public float getWidth() { + return mWidth; + } + + public float getHeight() { + return mHeight; + } + + public void setWidth(float mWidth) { + this.mWidth = mWidth; + } + + public void setHeight(float mHeight) { + this.mHeight = mHeight; + } + + public void setVisible(boolean visible) { + mIsShowing = visible; + } + + public int getColor() { + return R.color.default_scrim_color; + } + + public boolean isVisible() { + return mIsShowing; + } + + public void setAlpha(float alpha) { + mAlpha = alpha; + } + + public float getY() { + return 0.f; + } + + public float getAlpha() { + return mAlpha; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java index 48d31025..f1833ed 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/scene_layer/TabStripSceneLayer.java
@@ -14,6 +14,7 @@ import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton; import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutHelperManager; import org.chromium.chrome.browser.compositor.overlays.strip.StripLayoutTab; +import org.chromium.chrome.browser.compositor.overlays.strip.StripScrim; import org.chromium.chrome.browser.layouts.scene_layer.SceneLayer; import org.chromium.chrome.browser.layouts.scene_layer.SceneOverlayLayer; import org.chromium.ui.base.LocalizationUtils; @@ -80,6 +81,16 @@ TabStripSceneLayerJni.get().finishBuildingFrame(mNativePtr, TabStripSceneLayer.this); } + /** + * Updates tab strip scrim. + * @param scrim + */ + public void updateStripScrim(StripScrim scrim) { + TabStripSceneLayerJni.get().updateStripScrim(mNativePtr, TabStripSceneLayer.this, + scrim.getX(), scrim.getY(), scrim.getWidth() * mDpToPx, scrim.getHeight() * mDpToPx, + scrim.getColor(), scrim.getAlpha()); + } + private boolean shouldReaddBackground(int orientation) { // Sometimes layer trees do not get updated on rotation on Nexus 10. // This is a workaround that readds the background to prevent it. @@ -102,6 +113,8 @@ height, yOffset * mDpToPx, layoutHelper.getBackgroundTabBrightness(), layoutHelper.getBrightness(), shouldReaddBackground(layoutHelper.getOrientation())); + updateStripScrim(layoutHelper.getStripScrim()); + CompositorButton newTabButton = layoutHelper.getNewTabButton(); CompositorButton modelSelectorButton = layoutHelper.getModelSelectorButton(); boolean newTabButtonVisible = newTabButton.isVisible(); @@ -164,7 +177,9 @@ void finishBuildingFrame(long nativeTabStripSceneLayer, TabStripSceneLayer caller); void updateTabStripLayer(long nativeTabStripSceneLayer, TabStripSceneLayer caller, float width, float height, float yOffset, float backgroundTabBrightness, - float brightness, boolean shouldReaddBackground); + float brightness, boolean shouldReadBackground); + void updateStripScrim(long nativeTabStripSceneLayer, TabStripSceneLayer caller, float x, + float y, float width, float height, int color, float alpha); void updateNewTabButton(long nativeTabStripSceneLayer, TabStripSceneLayer caller, int resourceId, float x, float y, float width, float height, boolean visible, ResourceManager resourceManager);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java index b0dcf54..59fd66e4 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuCoordinator.java
@@ -413,4 +413,9 @@ } return null; } + + @VisibleForTesting + public ContextMenuDialog getDialogForTest() { + return mDialog; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java index ca97522..311ce41 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuHelper.java
@@ -27,7 +27,7 @@ import java.util.concurrent.TimeUnit; /** - * A helper class that handles generating context menus for {@link WebContents}s. + * A helper class that handles generating and dismissing context menus for {@link WebContents}. */ public class ContextMenuHelper { private static Callback<ContextMenuCoordinator> sMenuShownCallbackForTests; @@ -62,10 +62,7 @@ @CalledByNative private void destroy() { - if (mCurrentContextMenu != null) { - mCurrentContextMenu.dismiss(); - mCurrentContextMenu = null; - } + dismissContextMenu(); if (mCurrentNativeDelegate != null) mCurrentNativeDelegate.destroy(); if (mPopulatorFactory != null) mPopulatorFactory.onDestroy(); mNativeContextMenuHelper = 0; @@ -73,10 +70,7 @@ @CalledByNative private void setPopulatorFactory(ContextMenuPopulatorFactory populatorFactory) { - if (mCurrentContextMenu != null) { - mCurrentContextMenu.dismiss(); - mCurrentContextMenu = null; - } + dismissContextMenu(); if (mCurrentNativeDelegate != null) mCurrentNativeDelegate.destroy(); mCurrentPopulator = null; if (mPopulatorFactory != null) mPopulatorFactory.onDestroy(); @@ -151,6 +145,14 @@ displayContextMenu(topContentOffsetPx); } + @CalledByNative + private void dismissContextMenu() { + if (mCurrentContextMenu != null) { + mCurrentContextMenu.dismiss(); + mCurrentContextMenu = null; + } + } + /** * Record a histogram for a context menu shown even sliced by type. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuListView.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuListView.java index 17eabf6..07b9e56c 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuListView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ContextMenuListView.java
@@ -34,7 +34,8 @@ */ private int calculateWidth() { final int windowWidthPx = getResources().getDisplayMetrics().widthPixels; - final int maxWidth = getResources().getDimensionPixelSize(R.dimen.context_menu_max_width); + final int maxWidthFromRes = + getResources().getDimensionPixelSize(R.dimen.context_menu_max_width); final int lateralMargin = getResources().getDimensionPixelSize(R.dimen.context_menu_lateral_margin); @@ -44,8 +45,8 @@ final View frame = ((View) getParent()); assert frame.getId() == R.id.context_menu_frame; final int parentLateralPadding = frame.getPaddingLeft(); + final int maxWidth = Math.min(maxWidthFromRes, frame.getMeasuredWidth()); - return Math.min(maxWidth - 2 * parentLateralPadding, - windowWidthPx - 2 * lateralMargin - 2 * parentLateralPadding); + return Math.min(maxWidth, windowWidthPx - 2 * lateralMargin) - 2 * parentLateralPadding; } }
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 645e67f..6cc2827b 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
@@ -34,7 +34,9 @@ import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider; import org.chromium.chrome.browser.browserservices.intents.BrowserServicesIntentDataProvider.CustomTabsUiType; import org.chromium.chrome.browser.customtabs.content.CustomTabActivityTabProvider; +import org.chromium.chrome.browser.customtabs.dependency_injection.BaseCustomTabActivityComponent; import org.chromium.chrome.browser.customtabs.features.CustomTabNavigationBarController; +import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule; import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor; import org.chromium.chrome.browser.flags.AllCachedFieldTrialParameters; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -63,6 +65,8 @@ public static final AllCachedFieldTrialParameters EXPERIMENTS_FOR_AGSA_PARAMS = new AllCachedFieldTrialParameters(ChromeFeatureList.EXPERIMENTS_FOR_AGSA); + private CustomTabsOpenTimeRecorder mOpenTimeRecorder; + private CustomTabActivityTabProvider.Observer mTabChangeObserver = new CustomTabActivityTabProvider.Observer() { @Override @@ -82,6 +86,15 @@ }; @Override + protected BaseCustomTabActivityComponent createComponent( + ChromeActivityCommonsModule commonsModule) { + BaseCustomTabActivityComponent component = super.createComponent(commonsModule); + mOpenTimeRecorder = + new CustomTabsOpenTimeRecorder(getLifecycleDispatcher(), mNavigationController); + return component; + } + + @Override protected Drawable getBackgroundDrawable() { int initialBackgroundColor = mIntentDataProvider.getColorProvider().getInitialBackgroundColor(); @@ -158,6 +171,18 @@ } } + @Override + protected void handleFinishAndClose() { + mOpenTimeRecorder.updateCloseCause(); + super.handleFinishAndClose(); + } + + @Override + protected void onUserLeaveHint() { + mOpenTimeRecorder.onUserLeaveHint(); + super.onUserLeaveHint(); + } + private void resetPostMessageHandlersForCurrentSession() { Tab tab = mTabProvider.getTab(); WebContents webContents = tab == null ? null : tab.getWebContents();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java new file mode 100644 index 0000000..035e785 --- /dev/null +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabsOpenTimeRecorder.java
@@ -0,0 +1,76 @@ +// Copyright 2022 The Chromium 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.customtabs; + +import android.os.SystemClock; + +import androidx.annotation.IntDef; + +import org.chromium.base.metrics.RecordHistogram; +import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController; +import org.chromium.chrome.browser.customtabs.content.CustomTabActivityNavigationController.FinishReason; +import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher; +import org.chromium.chrome.browser.lifecycle.StartStopWithNativeObserver; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * Records how long CCTs are open. Only logs if CCTs are closed automatically + * without user intervention. + */ +class CustomTabsOpenTimeRecorder implements StartStopWithNativeObserver { + private final CustomTabActivityNavigationController mNavigationController; + + private long mOnStartTimestampMs; + + // This should be kept in sync with the definition |CustomTabsCloseCause| + // in tools/metrics/histograms/enums.xml. + @IntDef({CloseCause.USER_ACTION_CHROME, CloseCause.USER_ACTION_ANDROID, CloseCause.AUTOCLOSE}) + @Retention(RetentionPolicy.SOURCE) + public @interface CloseCause { + int USER_ACTION_CHROME = 0; + int USER_ACTION_ANDROID = 1; + int AUTOCLOSE = 2; + int COUNT = 3; + } + + private @CloseCause int mCloseCause; + + public CustomTabsOpenTimeRecorder(ActivityLifecycleDispatcher lifecycleDispatcher, + CustomTabActivityNavigationController navigationController) { + lifecycleDispatcher.register(this); + mNavigationController = navigationController; + } + + @Override + public void onStartWithNative() { + mOnStartTimestampMs = SystemClock.elapsedRealtime(); + mCloseCause = CloseCause.AUTOCLOSE; + } + + @Override + public void onStopWithNative() { + assert mOnStartTimestampMs != 0; + RecordHistogram.recordEnumeratedHistogram( + "CustomTabs.CloseCause", mCloseCause, CloseCause.COUNT); + if (mCloseCause == CloseCause.AUTOCLOSE) { + long duration = SystemClock.elapsedRealtime() - mOnStartTimestampMs; + RecordHistogram.recordLongTimesHistogram( + "CustomTabs.AutoclosedSessionDuration", duration); + } + mOnStartTimestampMs = 0; + } + + void updateCloseCause() { + if (mNavigationController.getFinishReason() == FinishReason.USER_NAVIGATION) { + mCloseCause = CloseCause.USER_ACTION_CHROME; + } + } + + void onUserLeaveHint() { + mCloseCause = CloseCause.USER_ACTION_ANDROID; + } +}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java index 12cdc4e..16de982 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/content/CustomTabActivityNavigationController.java
@@ -110,6 +110,8 @@ private boolean mIsHandlingUserNavigation; + private @FinishReason int mFinishReason; + private final CustomTabActivityTabProvider.Observer mTabObserver = new CustomTabActivityTabProvider.Observer() { @@ -306,6 +308,7 @@ public void finish(@FinishReason int reason) { if (mIsFinishing) return; mIsFinishing = true; + mFinishReason = reason; if (reason != REPARENTING) { // Closing the activity destroys the renderer as well. Re-create a spare renderer some @@ -322,6 +325,10 @@ } } + public @FinishReason int getFinishReason() { + return mFinishReason; + } + /** * Sets a {@link FinishHandler} to be notified when the custom tab is being closed. */
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java index 4904aa9..f736b6d 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadActivity.java
@@ -7,6 +7,7 @@ import android.app.Activity; import android.os.Bundle; +import org.chromium.chrome.browser.BackPressHelper; import org.chromium.chrome.browser.SnackbarActivity; import org.chromium.chrome.browser.download.home.DownloadManagerCoordinator; import org.chromium.chrome.browser.download.home.DownloadManagerCoordinatorFactoryHelper; @@ -77,6 +78,8 @@ setContentView(mDownloadCoordinator.getView()); if (!showPrefetchContent) mDownloadCoordinator.updateForUrl(mCurrentUrl); mDownloadCoordinator.addObserver(mUiObserver); + BackPressHelper.create( + this, getOnBackPressedDispatcher(), mDownloadCoordinator::onBackPressed); } @Override @@ -93,12 +96,6 @@ } @Override - public void onBackPressed() { - if (mDownloadCoordinator.onBackPressed()) return; - super.onBackPressed(); - } - - @Override protected void onDestroy() { mDownloadCoordinator.removeObserver(mUiObserver); mDownloadCoordinator.destroy();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java index b5872d7..dc59f32b 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/FirstRunActivity.java
@@ -27,6 +27,7 @@ import org.chromium.base.supplier.OneshotSupplierImpl; import org.chromium.base.supplier.Supplier; import org.chromium.chrome.R; +import org.chromium.chrome.browser.BackPressHelper; import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.fonts.FontPreloader; import org.chromium.chrome.browser.metrics.UmaUtils; @@ -131,6 +132,15 @@ */ private FirstRunPagerAdapter mPagerAdapter; + @Override + protected void onPreCreate() { + super.onPreCreate(); + BackPressHelper.create(this, getOnBackPressedDispatcher(), () -> { + handleBackPressed(); + return true; + }); + } + /** Creates first page and sets up adapter. Should result UI being shown on the screen. */ private void createFirstPage() { FREMobileIdentityConsistencyFieldTrial.createFirstRunTrial(); @@ -399,8 +409,7 @@ } } - @Override - public void onBackPressed() { + private void handleBackPressed() { // Terminate if we are still waiting for the native or for Android EDU / GAIA Child checks. if (!mPostNativeAndPolicyPagesCreated) { abortFirstRunExperience();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java index 37b67ec..fca7ded 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/firstrun/LightweightFirstRunActivity.java
@@ -23,6 +23,7 @@ import org.chromium.base.ThreadUtils; import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; +import org.chromium.chrome.browser.BackPressHelper; import org.chromium.chrome.browser.customtabs.CustomTabActivity; import org.chromium.chrome.browser.enterprise.util.EnterpriseInfo; import org.chromium.components.signin.ChildAccountStatus; @@ -75,6 +76,15 @@ } @Override + protected void onPreCreate() { + super.onPreCreate(); + BackPressHelper.create(this, getOnBackPressedDispatcher(), () -> { + abortFirstRunExperience(); + return true; + }); + } + + @Override public void triggerLayoutInflation() { setFinishOnTouchOutside(true); @@ -205,11 +215,6 @@ } @Override - public void onBackPressed() { - abortFirstRunExperience(); - } - - @Override public void onDestroy() { super.onDestroy();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryActivity.java index a08ecbf..6635967 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryActivity.java
@@ -9,6 +9,7 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.IntentUtils; +import org.chromium.chrome.browser.BackPressHelper; import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.SnackbarActivity; @@ -27,6 +28,7 @@ mHistoryManager = new HistoryManager( this, true, getSnackbarManager(), isIncognito, /* Supplier<Tab>= */ null); setContentView(mHistoryManager.getView()); + BackPressHelper.create(this, getOnBackPressedDispatcher(), mHistoryManager::onBackPressed); } @Override @@ -40,9 +42,4 @@ HistoryManager getHistoryManagerForTests() { return mHistoryManager; } - - @Override - public void onBackPressed() { - if (!mHistoryManager.onBackPressed()) super.onBackPressed(); - } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadLaterIPHController.java b/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadLaterIPHController.java index 1ad3c191..8976000 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadLaterIPHController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadLaterIPHController.java
@@ -32,10 +32,15 @@ */ public ReadLaterIPHController( Activity activity, View toolbarMenuButton, AppMenuHandler appMenuHandler) { + this(activity, toolbarMenuButton, appMenuHandler, + new UserEducationHelper(activity, new Handler(Looper.getMainLooper()))); + } + + ReadLaterIPHController(Activity activity, View toolbarMenuButton, AppMenuHandler appMenuHandler, + UserEducationHelper userEducationHelper) { mToolbarMenuButton = toolbarMenuButton; mAppMenuHandler = appMenuHandler; - mUserEducationHelper = - new UserEducationHelper(activity, new Handler(Looper.getMainLooper())); + mUserEducationHelper = userEducationHelper; } /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java index 63e15ab..8d57263 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/read_later/ReadingListUtils.java
@@ -29,6 +29,7 @@ /** Utility functions for reading list feature. */ public final class ReadingListUtils { private static Boolean sReadingListSupportedForTesting; + private static Boolean sSkipShowSaveFlowForTesting; /** Returns whether the URL can be added as reading list article. */ public static boolean isReadingListSupported(GURL url) { @@ -41,9 +42,8 @@ } /** Removes from the reading list the entry for the current tab. */ - public static void deleteFromReadingList( + public static void deleteFromReadingList(final BookmarkModel bookmarkModel, SnackbarManager snackbarManager, Activity activity, Tab currentTab) { - final BookmarkModel bookmarkModel = new BookmarkModel(); // This undo controller will dismiss itself when any action is taken. BookmarkUndoController.createOneshotBookmarkUndoController( activity, bookmarkModel, snackbarManager); @@ -70,14 +70,14 @@ * * @param activity The current Activity. * @param bottomsheetController The BottomsheetController, used to show the save flow. - * @param bookmarkModel The BookmarkModel which is used for bookmark operations. + * @param bookmarkBridge The BookmarkBridge which is used for bookmark operations. * @param bookmarkId The existing BookmarkId. * @param bookmarkType The intended bookmark type. * @return Whether the given bookmark item has been type-swapped and the save flow shown. */ public static boolean maybeTypeSwapAndShowSaveFlow(@NonNull Activity activity, @NonNull BottomSheetController bottomsheetController, - @NonNull BookmarkModel bookmarkModel, @NonNull BookmarkId bookmarkId, + @NonNull BookmarkBridge bookmarkBridge, @NonNull BookmarkId bookmarkId, @BookmarkType int bookmarkType) { if (!ReadingListFeatures.shouldAllowBookmarkTypeSwapping() || bookmarkId == null || bookmarkId.getType() != BookmarkType.NORMAL @@ -90,7 +90,8 @@ List<BookmarkId> bookmarkIds = new ArrayList<>(); bookmarkIds.add(bookmarkId); ReadingListUtils.typeSwapBookmarksIfNecessary( - bookmarkModel, bookmarkIds, bookmarkModel.getReadingListFolder()); + bookmarkBridge, bookmarkIds, bookmarkBridge.getReadingListFolder()); + if (sSkipShowSaveFlowForTesting) return true; BookmarkUtils.showSaveFlow(activity, bottomsheetController, /*fromExplicitTrackUi=*/false, bookmarkIds.get(0), /*wasBookmarkMoved=*/true); return true; @@ -140,4 +141,9 @@ public static void setReadingListSupportedForTesting(Boolean supported) { sReadingListSupportedForTesting = supported; } + + /** For cases where we don't want to mock the entire bookmarks save flow infra. */ + public static void setSkipShowSaveFlowForTesting(Boolean skipShowSaveFlowForTesting) { + sSkipShowSaveFlowForTesting = skipShowSaveFlowForTesting; + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java index 3ecd905..3a6d3e0 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
@@ -29,6 +29,7 @@ import org.chromium.base.IntentUtils; import org.chromium.chrome.R; import org.chromium.chrome.browser.ApplicationLifetime; +import org.chromium.chrome.browser.BackPressHelper; import org.chromium.chrome.browser.ChromeBaseAppCompatActivity; import org.chromium.chrome.browser.LaunchIntentDispatcher; import org.chromium.chrome.browser.browsing_data.ClearBrowsingDataFragmentBasic; @@ -154,6 +155,7 @@ configureWideDisplayStyle(); setStatusBarColor(); initBottomSheet(); + BackPressHelper.create(this, getOnBackPressedDispatcher(), this::handleBackPressed); } @Override @@ -334,18 +336,11 @@ return super.onOptionsItemSelected(item); } - @Override - public void onBackPressed() { + private boolean handleBackPressed() { Fragment activeFragment = getMainFragment(); - if (!(activeFragment instanceof OnBackPressedListener)) { - super.onBackPressed(); - return; - } + if (!(activeFragment instanceof OnBackPressedListener)) return false; OnBackPressedListener listener = (OnBackPressedListener) activeFragment; - if (!listener.onBackPressed()) { - // Fragment hasn't handled this event, fall back to AppCompatActivity handling. - super.onBackPressed(); - } + return listener.onBackPressed(); } @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareRegistrationCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareRegistrationCoordinator.java index cc99860e..5c44ee1 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/share/ShareRegistrationCoordinator.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/share/ShareRegistrationCoordinator.java
@@ -13,6 +13,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.chromium.base.ContextUtils; import org.chromium.base.IntentUtils; @@ -80,7 +81,7 @@ intent.putExtra(EXTRA_TYPE, action); intent.putExtra(ShareHelper.EXTRA_TASK_ID, taskId); - context.sendBroadcast(intent); + LocalBroadcastManager.getInstance(context).sendBroadcast(intent); } private final Map<String, Runnable> mShareMap = new HashMap<>(); @@ -104,14 +105,15 @@ mHashCodeToken = hashCode(); sReceiverMap.put(mTaskId, this); - mContext.registerReceiver(this, new IntentFilter(RECEIVER_ACTION)); + LocalBroadcastManager.getInstance(mContext).registerReceiver( + this, new IntentFilter(RECEIVER_ACTION)); } /** Destroy the receiver. */ public void destroy() { mIsDestroyed = true; sReceiverMap.remove(mTaskId); - mContext.unregisterReceiver(this); + LocalBroadcastManager.getInstance(mContext).unregisterReceiver(this); mContext = null; }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java index 3efe88d..9149294 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/survey/ChromeSurveyController.java
@@ -80,6 +80,7 @@ @VisibleForTesting static final String SITE_ID_PARAM_NAME = "site-id"; private static boolean sForceUmaEnabledForTesting; + private static boolean sMessageShown; /** * Reasons that the user was rejected from being selected for a survey @@ -239,6 +240,18 @@ if (ChromeFeatureList.isEnabled(ChromeFeatureList.MESSAGES_FOR_ANDROID_CHROME_SURVEY) && mMessageDispatcher != null) { + // Return early if the message is already shown once. + if (sMessageShown) { + String logMessage = String.format( + "The survey prompt for survey with ID %s has already been shown.", siteId); + Log.w(TAG, logMessage); + PostTask.postTask(TaskTraits.BEST_EFFORT_MAY_BLOCK, + () + -> ChromePureJavaExceptionReporter.reportJavaException( + new Throwable(logMessage))); + return; + } + // Return early without displaying the message prompt if the survey has expired. if (SurveyController.getInstance().isSurveyExpired(siteId)) { String logMessage = @@ -328,6 +341,7 @@ mMessageDispatcher.enqueueMessage( message, mSurveyPromptTab.getWebContents(), MessageScopeType.NAVIGATION, false); + sMessageShown = true; } else { InfoBarContainer.get(tab).addAnimationListener(this); @@ -716,4 +730,16 @@ public static Long getRequiredVisibilityDurationMs() { return REQUIRED_VISIBILITY_DURATION_MS; } + + /** @return Whether the message has been previously shown to the client. */ + @VisibleForTesting + public static boolean isMessageShown() { + return sMessageShown; + } + + // Reset sMessageShown for testing. + @VisibleForTesting + public static void resetMessageShownForTesting() { + sMessageShown = false; + } }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/app/ContextMenuDragTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/app/ContextMenuDragTest.java new file mode 100644 index 0000000..0682e602 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/app/ContextMenuDragTest.java
@@ -0,0 +1,216 @@ +// Copyright 2022 The Chromium 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.app; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.mock; + +import android.graphics.Bitmap; +import android.graphics.Rect; +import android.os.Build.VERSION_CODES; +import android.support.test.InstrumentationRegistry; +import android.view.DragEvent; +import android.view.View; + +import androidx.test.filters.SmallTest; + +import org.junit.After; +import org.junit.AfterClass; +import org.junit.Assert; +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.Batch; +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.CriteriaHelper; +import org.chromium.base.test.util.DisableIf; +import org.chromium.chrome.browser.contextmenu.ContextMenuCoordinator; +import org.chromium.chrome.browser.firstrun.FirstRunStatus; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.flags.ChromeSwitches; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule; +import org.chromium.chrome.test.util.ChromeApplicationTestUtils; +import org.chromium.chrome.test.util.browser.Features; +import org.chromium.chrome.test.util.browser.contextmenu.ContextMenuUtils; +import org.chromium.content_public.browser.test.util.DOMUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.content_public.common.ContentFeatures; +import org.chromium.net.test.EmbeddedTestServer; +import org.chromium.ui.base.DropDataAndroid; +import org.chromium.ui.base.ViewAndroidDelegate; + +import java.util.concurrent.TimeoutException; + +/** + * Integration tests for drag interactions with context menu. + */ +// clang-format off +@RunWith(ChromeJUnit4ClassRunner.class) +@DisableIf.Build(sdk_is_less_than = VERSION_CODES.N) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, + "enable-blink-features=TouchDragAndContextMenu"}) +@Features.EnableFeatures({ChromeFeatureList.CONTEXT_MENU_POPUP_STYLE, + ContentFeatures.DRAG_AND_DROP}) +@Batch(Batch.PER_CLASS) +public class ContextMenuDragTest { + // clang-format on + + // Test distance + private static final int TEST_MIN_DIST = 10; + private static final String TEST_PATH = + "/chrome/test/data/android/contextmenu/context_menu_test.html"; + private static final String TEST_IMAGE_ID = "testImage"; + + @ClassRule + public static ChromeTabbedActivityTestRule sActivityTestRule = + new ChromeTabbedActivityTestRule(); + + static TestDragAndDropDelegate sTestDragAndDropDelegate = new TestDragAndDropDelegate(); + + @Rule + public BlankCTATabInitialStateRule mTestRule = + new BlankCTATabInitialStateRule(sActivityTestRule, false); + + private EmbeddedTestServer mTestServer; + + private ContextMenuCoordinator mContextMenu; + private String mTestUrl; + private Tab mTab; + + @BeforeClass + public static void setupBeforeClass() { + TestThreadUtils.runOnUiThreadBlocking(() -> FirstRunStatus.setFirstRunFlowComplete(true)); + + // Stop the real call to android View#startDragAndDrop. Test file do not have real touches + // over the screen so there's no way to end the drag event properly. Doing this in + // @BeforeClass since ViewAndroidDelegate is created earlier than @Before due to batching. + sTestDragAndDropDelegate = new TestDragAndDropDelegate(); + ViewAndroidDelegate.setDragAndDropDelegateForTest(sTestDragAndDropDelegate); + } + + @Before + public void setUp() { + mTestServer = EmbeddedTestServer.createAndStartServer(InstrumentationRegistry.getContext()); + mTestUrl = mTestServer.getURL(TEST_PATH); + + sActivityTestRule.loadUrl(mTestUrl); + mTab = sActivityTestRule.getActivity().getActivityTab(); + CriteriaHelper.pollUiThread(() -> mTab.isUserInteractable() && !mTab.isLoading()); + ChromeApplicationTestUtils.assertWaitForPageScaleFactorMatch( + sActivityTestRule.getActivity(), 0.5f); + } + + @After + public void tearDown() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + if (mContextMenu != null) mContextMenu.dismiss(); + }); + mTestServer.stopAndDestroyServer(); + sTestDragAndDropDelegate.reset(); + } + + @AfterClass + public static void tearDownAfterClass() { + ViewAndroidDelegate.setDragAndDropDelegateForTest(null); + TestThreadUtils.runOnUiThreadBlocking(() -> FirstRunStatus.setFirstRunFlowComplete(false)); + } + + @Test + @SmallTest + public void testTriggerContextMenu_Image() throws TimeoutException { + longPressOpenContextMenu(TEST_IMAGE_ID); + DropDataAndroid data = getDropData(); + Assert.assertTrue("Drop data should have Image.", data.hasImage()); + } + + @Test + @SmallTest + @CommandLineFlags. + Add({"force-fieldtrial-params=Study.Group:DragAndDropMovementThresholdDipParam/" + + TEST_MIN_DIST}) + public void + testTriggerContextMenuWithDrag() throws TimeoutException { + longPressOpenContextMenu(TEST_IMAGE_ID); + + final Rect location = DOMUtils.getNodeBounds(mTab.getWebContents(), TEST_IMAGE_ID); + final int jitterRange = 1; + + // Clank is not forwarding drag start event to blink; instead, browser only remembers the + // first drag events as the starting point of context menu. + DragEvent event1 = mockDragEvent( + location.centerX(), location.centerY(), DragEvent.ACTION_DRAG_LOCATION); + DragEvent event2 = mockDragEvent(location.centerX() + jitterRange, + location.centerY() + jitterRange, DragEvent.ACTION_DRAG_LOCATION); + TestThreadUtils.runOnUiThreadBlocking(() -> { + mTab.getContentView().onDragEvent(event1); + mTab.getContentView().onDragEvent(event2); + }); + assertContextMenuShowing(true); + + final int minDragThresholdPx = + (int) (sActivityTestRule.getActivity().getResources().getDisplayMetrics().density + * TEST_MIN_DIST) + + 1; + DragEvent event3 = mockDragEvent(location.centerX() + minDragThresholdPx, + location.centerY() + minDragThresholdPx, DragEvent.ACTION_DRAG_LOCATION); + TestThreadUtils.runOnUiThreadBlocking(() -> { mTab.getContentView().onDragEvent(event3); }); + assertContextMenuShowing(false); + } + + private void longPressOpenContextMenu(String nodeId) throws TimeoutException { + mContextMenu = ContextMenuUtils.openContextMenu(mTab, nodeId); + Assert.assertNotNull("Context menu is null.", mContextMenu); + assertContextMenuShowing(true); + } + + private void assertContextMenuShowing(boolean showing) { + Assert.assertNotNull("Context menu dialog is null.", mContextMenu.getDialogForTest()); + Assert.assertEquals("Context menu dialog is not showing.", showing, + mContextMenu.getDialogForTest().isShowing()); + } + + private DropDataAndroid getDropData() { + Assert.assertEquals("#startDragAndDrop is not called.", 1, + sTestDragAndDropDelegate.startDragAndDropCallCount); + Assert.assertNotNull("DropDataAndroid is null.", sTestDragAndDropDelegate.lastDropData); + return sTestDragAndDropDelegate.lastDropData; + } + + private DragEvent mockDragEvent(int x, int y, int actionType) { + DragEvent event = mock(DragEvent.class); + doReturn(actionType).when(event).getAction(); + doReturn((float) x).when(event).getX(); + doReturn((float) y).when(event).getY(); + return event; + } + + // Test impl for ViewAndroidDelegate.DragAndDropDelegate as compromise that mockito does not + // work well with @BeforeClass. + static class TestDragAndDropDelegate implements ViewAndroidDelegate.DragAndDropDelegate { + public DropDataAndroid lastDropData; + public int startDragAndDropCallCount; + + @Override + public boolean startDragAndDrop( + View containerView, Bitmap shadowImage, DropDataAndroid dropData) { + lastDropData = dropData; + startDragAndDropCallCount += 1; + + return true; + } + + void reset() { + lastDropData = null; + startDragAndDropCallCount = 0; + } + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java index 673d68c..05e2a1a 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/compositor/overlays/strip/TabStripTest.java
@@ -25,6 +25,7 @@ import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Restriction; import org.chromium.chrome.browser.compositor.layouts.components.CompositorButton; +import org.chromium.chrome.browser.flags.ChromeFeatureList; import org.chromium.chrome.browser.flags.ChromeSwitches; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tabmodel.TabModel; @@ -35,6 +36,7 @@ import org.chromium.chrome.test.batch.BlankCTATabInitialStateRule; import org.chromium.chrome.test.util.ChromeTabUtils; import org.chromium.chrome.test.util.TabStripUtils; +import org.chromium.chrome.test.util.browser.Features; import org.chromium.content_public.browser.test.util.DOMUtils; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.base.LocalizationUtils; @@ -854,6 +856,75 @@ } /** + * Tests strip scrim when overview mode shows-up. + */ + @Test + @LargeTest + @Restriction(UiRestriction.RESTRICTION_TYPE_TABLET) + @Feature({"TabStrip"}) + @Features.EnableFeatures(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS) + public void testStripScrimOnShowingOverviewMode() throws Throwable { + // Create second tab. Second tab is active. + ChromeTabUtils.newTabFromMenu( + InstrumentationRegistry.getInstrumentation(), sActivityTestRule.getActivity()); + // Enter overview. + enterOverviewMode(); + + final StripLayoutHelperManager manager = + TabStripUtils.getStripLayoutHelperManager(sActivityTestRule.getActivity()); + + // Verify scrim is visible. + Assert.assertTrue(manager.getStripScrim().isVisible()); + + // Try to click first tab. + TabStripUtils.clickTab( + TabStripUtils.findStripLayoutTab(sActivityTestRule.getActivity(), false, + sActivityTestRule.getActivity().getCurrentTabModel().getTabAt(0).getId()), + InstrumentationRegistry.getInstrumentation(), sActivityTestRule.getActivity()); + + // Verify first tab not selectable + Assert.assertNotEquals("The first tab should not be selected", + sActivityTestRule.getActivity().getCurrentTabModel().index(), 0); + } + + /** + * Tests strip scrim disappears when overview mode is hidden. + */ + @Test + @LargeTest + @Restriction(UiRestriction.RESTRICTION_TYPE_TABLET) + @Feature({"TabStrip"}) + @Features.EnableFeatures(ChromeFeatureList.GRID_TAB_SWITCHER_FOR_TABLETS) + public void testStripScrimOnHidingOverviewMode() throws Throwable { + // Enter overview. + enterOverviewMode(); + + final StripLayoutHelperManager manager = + TabStripUtils.getStripLayoutHelperManager(sActivityTestRule.getActivity()); + + // Verify scrim is visible. + Assert.assertTrue(manager.getStripScrim().isVisible()); + + // Exit overview. + exitOverviewMode(); + + // Verify scrim is invisible. + Assert.assertTrue(!manager.getStripScrim().isVisible()); + } + + private void exitOverviewMode() { + TestThreadUtils.runOnUiThreadBlocking( + () -> sActivityTestRule.getActivity().getLayoutManager().hideOverview(false)); + Assert.assertFalse(sActivityTestRule.getActivity().getLayoutManager().overviewVisible()); + } + + private void enterOverviewMode() { + TestThreadUtils.runOnUiThreadBlocking( + () -> sActivityTestRule.getActivity().getLayoutManager().showOverview(false)); + Assert.assertTrue(sActivityTestRule.getActivity().getLayoutManager().overviewVisible()); + } + + /** * Take a model index and figure out which index it will be in the TabStrip's view hierarchy. * @param tabCount The number of tabs. * @param selectedIndex The index of the selected tab.
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerIntegrationTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerIntegrationTest.java index 9bfe43d4..a6188e2 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerIntegrationTest.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerIntegrationTest.java
@@ -123,6 +123,7 @@ SurveyController.setInstanceForTesting(null); mSharedPreferenceManager.removeKey(mPrefKey); ChromeSurveyController.forceIsUMAEnabledForTesting(false); + ChromeSurveyController.resetMessageShownForTesting(); } @Test
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/BackPressHelperUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/BackPressHelperUnitTest.java new file mode 100644 index 0000000..65f718b --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/BackPressHelperUnitTest.java
@@ -0,0 +1,89 @@ +// Copyright 2022 The Chromium 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; + +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +import androidx.activity.OnBackPressedDispatcher; +import androidx.lifecycle.Lifecycle; +import androidx.lifecycle.LifecycleOwner; +import androidx.lifecycle.LifecycleRegistry; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; + +/** + * Unit tests for {@link org.chromium.chrome.browser.BackPressHelper}. + */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +public class BackPressHelperUnitTest { + @Mock + private BackPressHelper.BackPressedHandler mBackPressedHandler; + @Mock + private BackPressHelper.BackPressedHandler mBackPressedHandler2; + @Mock + private LifecycleOwner mLifecycleOwner; + private LifecycleRegistry mLifecycle; + @Mock + private Runnable mFallbackRunnable; + + private OnBackPressedDispatcher mOnBackPressedDispatcher; + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mLifecycle = new LifecycleRegistry(mLifecycleOwner); + mOnBackPressedDispatcher = new OnBackPressedDispatcher(mFallbackRunnable); + doReturn(mLifecycle).when(mLifecycleOwner).getLifecycle(); + mLifecycle.setCurrentState(Lifecycle.State.CREATED); + } + + @Test + public void testNextCallbackNotInvokedIfAlreadyConsumed() { + doReturn(true).when(mBackPressedHandler).onBackPressed(); + + // The last-added one is invoked first: mBackPressedHandler -> mBackPressedHandler2 + BackPressHelper.create(mLifecycleOwner, mOnBackPressedDispatcher, mBackPressedHandler2); + BackPressHelper.create(mLifecycleOwner, mOnBackPressedDispatcher, mBackPressedHandler); + mLifecycle.setCurrentState(Lifecycle.State.STARTED); + mOnBackPressedDispatcher.onBackPressed(); + + verify(mBackPressedHandler).onBackPressed(); + verify(mBackPressedHandler2, never()).onBackPressed(); + verify(mFallbackRunnable, never()).run(); + } + + @Test + public void testInvokeNextCallbackIfNotConsumed() { + doReturn(false).when(mBackPressedHandler).onBackPressed(); + doReturn(true).when(mBackPressedHandler2).onBackPressed(); + BackPressHelper.create(mLifecycleOwner, mOnBackPressedDispatcher, mBackPressedHandler2); + BackPressHelper.create(mLifecycleOwner, mOnBackPressedDispatcher, mBackPressedHandler); + mLifecycle.setCurrentState(Lifecycle.State.STARTED); + mOnBackPressedDispatcher.onBackPressed(); + + verify(mBackPressedHandler).onBackPressed(); + verify(mBackPressedHandler2).onBackPressed(); + verify(mFallbackRunnable, never()).run(); + } + + @Test + public void testInvokeFallbackRunnableIfNotHandled() { + doReturn(false).when(mBackPressedHandler).onBackPressed(); + BackPressHelper.create(mLifecycleOwner, mOnBackPressedDispatcher, mBackPressedHandler); + mLifecycle.setCurrentState(Lifecycle.State.STARTED); + mOnBackPressedDispatcher.onBackPressed(); + + verify(mFallbackRunnable).run(); + } +}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/base/DexFixerTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/base/DexFixerTest.java index 210dccee..c13758b 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/base/DexFixerTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/base/DexFixerTest.java
@@ -33,7 +33,6 @@ import org.chromium.base.BuildInfo; import org.chromium.base.ContextUtils; -import org.chromium.base.metrics.test.ShadowRecordHistogram; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.preferences.ChromePreferenceKeys; import org.chromium.chrome.browser.preferences.SharedPreferencesManager; @@ -45,7 +44,7 @@ */ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE, sdk = Build.VERSION_CODES.O_MR1, - shadows = {ShadowRecordHistogram.class, DexFixerTest.ShadowOs.class}) + shadows = {DexFixerTest.ShadowOs.class}) public class DexFixerTest { @Implements(Os.class) public static class ShadowOs { @@ -72,25 +71,9 @@ @After public void tearDown() { - ShadowRecordHistogram.reset(); DexFixer.setHasIsolatedSplits(false); } - private static int getReason() { - int ret = -1; - for (int i = 0; i < DexFixerReason.COUNT; ++i) { - int count = - ShadowRecordHistogram.getHistogramValueCountForTesting("Android.DexFixer", i); - if (count > 0) { - assertThat(count).isEqualTo(1); - assertThat(ret).isEqualTo(-1); - ret = i; - } - } - assertThat(ret).isNotEqualTo(-1); - return ret; - } - private void verifyDexOpt() { try { verify(mMockRuntime) @@ -102,30 +85,31 @@ @Test public void testFixDexIfNecessary_notNeeded() { - DexFixer.fixDexIfNecessary(mMockRuntime); - assertThat(getReason()).isEqualTo(DexFixerReason.NOT_NEEDED); + @DexFixerReason + int reason = DexFixer.fixDexIfNecessary(mMockRuntime); + assertThat(reason).isEqualTo(DexFixerReason.NOT_NEEDED); verifyNoMoreInteractions(mMockRuntime); } @Test public void testFixDexIfNecessary_notReadable() { ShadowOs.sWorldReadable = false; - DexFixer.fixDexIfNecessary(mMockRuntime); - assertThat(getReason()).isEqualTo(DexFixerReason.NOT_READABLE); + @DexFixerReason + int reason = DexFixer.fixDexIfNecessary(mMockRuntime); + assertThat(reason).isEqualTo(DexFixerReason.NOT_READABLE); verifyDexOpt(); } @Test public void testFixDexIfNecessary_update() { DexFixer.setHasIsolatedSplits(true); - DexFixer.fixDexIfNecessary(mMockRuntime); - assertThat(getReason()).isEqualTo(DexFixerReason.O_MR1_AFTER_UPDATE); + @DexFixerReason + int reason = DexFixer.fixDexIfNecessary(mMockRuntime); + assertThat(reason).isEqualTo(DexFixerReason.O_MR1_AFTER_UPDATE); verifyDexOpt(); - // Second time should be okay. - ShadowRecordHistogram.reset(); - DexFixer.fixDexIfNecessary(mMockRuntime); - assertThat(getReason()).isEqualTo(DexFixerReason.NOT_NEEDED); + reason = DexFixer.fixDexIfNecessary(mMockRuntime); + assertThat(reason).isEqualTo(DexFixerReason.NOT_NEEDED); verifyNoMoreInteractions(mMockRuntime); } @@ -140,8 +124,9 @@ BuildInfo.getInstance().versionCode); ShadowDexFile.setIsDexOptNeeded(true); - DexFixer.fixDexIfNecessary(mMockRuntime); - assertThat(getReason()).isEqualTo(DexFixerReason.O_MR1_CORRUPTED); + @DexFixerReason + int reason = DexFixer.fixDexIfNecessary(mMockRuntime); + assertThat(reason).isEqualTo(DexFixerReason.O_MR1_CORRUPTED); verifyDexOpt(); } @@ -155,8 +140,9 @@ ChromePreferenceKeys.ISOLATED_SPLITS_DEX_COMPILE_VERSION, BuildInfo.getInstance().versionCode); - DexFixer.fixDexIfNecessary(mMockRuntime); - assertThat(getReason()).isEqualTo(DexFixerReason.NOT_READABLE); + @DexFixerReason + int reason = DexFixer.fixDexIfNecessary(mMockRuntime); + assertThat(reason).isEqualTo(DexFixerReason.NOT_READABLE); verifyDexOpt(); } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadLaterIPHControllerUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadLaterIPHControllerUnitTest.java new file mode 100644 index 0000000..83387dc --- /dev/null +++ b/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadLaterIPHControllerUnitTest.java
@@ -0,0 +1,111 @@ +// Copyright 2022 The Chromium 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.read_later; + +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.verify; + +import android.app.Activity; +import android.content.Context; +import android.content.res.Resources; +import android.view.View; + +import androidx.test.filters.SmallTest; + +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TestRule; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; +import org.robolectric.annotation.Config; + +import org.chromium.base.test.BaseRobolectricTestRunner; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.ui.appmenu.AppMenuHandler; +import org.chromium.chrome.browser.user_education.IPHCommand; +import org.chromium.chrome.browser.user_education.UserEducationHelper; +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.Features.JUnitProcessor; + +/** Unit test for {@link ReadLaterIPHController}. */ +@RunWith(BaseRobolectricTestRunner.class) +@Config(manifest = Config.NONE) +@EnableFeatures(ChromeFeatureList.READ_LATER) +public class ReadLaterIPHControllerUnitTest { + @Rule + public TestRule mFeaturesProcessor = new JUnitProcessor(); + + @Mock + Activity mActivity; + @Mock + View mToolbarMenuButton; + @Mock + AppMenuHandler mAppMenuHandler; + @Mock + UserEducationHelper mUserEducationHelper; + @Mock + Context mContext; + @Mock + Resources mResources; + @Captor + ArgumentCaptor<IPHCommand> mIPHCommandCaptor; + + ReadLaterIPHController mController; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + doReturn(mResources).when(mContext).getResources(); + doReturn(mContext).when(mToolbarMenuButton).getContext(); + + mController = new ReadLaterIPHController( + mActivity, mToolbarMenuButton, mAppMenuHandler, mUserEducationHelper); + } + + @Test + @SmallTest + public void onCopyContextMenuItemClicked() { + mController.onCopyContextMenuItemClicked(); + verify(mUserEducationHelper).requestShowIPH(any()); + } + + @Test + @SmallTest + @DisableFeatures(ChromeFeatureList.READ_LATER) + public void onCopyContextMenuItemClicked_FeatureDisabled() { + mController.onCopyContextMenuItemClicked(); + verify(mUserEducationHelper, Mockito.times(0)).requestShowIPH(any()); + } + + @Test + @SmallTest + public void showColdStartIPH() { + mController.showColdStartIPH(); + verify(mUserEducationHelper).requestShowIPH(mIPHCommandCaptor.capture()); + + IPHCommand command = mIPHCommandCaptor.getValue(); + command.onShowCallback.run(); + verify(mAppMenuHandler).setMenuHighlight(R.id.all_bookmarks_menu_id); + + command.onDismissCallback.run(); + verify(mAppMenuHandler).clearMenuHighlight(); + } + + @Test + @SmallTest + @DisableFeatures(ChromeFeatureList.READ_LATER) + public void showColdStartIPH_FeatureDisabled() { + mController.showColdStartIPH(); + verify(mUserEducationHelper, Mockito.times(0)).requestShowIPH(any()); + } +} \ No newline at end of file
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java index 33c2300c..b9cde46 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/read_later/ReadingListUtilsUnitTest.java
@@ -4,15 +4,22 @@ package org.chromium.chrome.browser.read_later; +import static org.mockito.Mockito.any; +import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.verify; +import android.app.Activity; + import androidx.test.filters.SmallTest; import org.junit.Assert; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; import org.chromium.base.FeatureList; @@ -20,9 +27,13 @@ import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.bookmarks.BookmarkBridge; import org.chromium.chrome.browser.bookmarks.BookmarkBridge.BookmarkItem; +import org.chromium.chrome.browser.bookmarks.BookmarkModel; import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.tab.Tab; +import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; import org.chromium.components.bookmarks.BookmarkId; import org.chromium.components.bookmarks.BookmarkType; +import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; @@ -32,9 +43,41 @@ @RunWith(BaseRobolectricTestRunner.class) @Config(manifest = Config.NONE) public class ReadingListUtilsUnitTest { + @Mock + BookmarkBridge mBookmarkModel; + + @Mock + BookmarkId mBookmarkId; + @Mock + BookmarkItem mBookmarkItem; + @Mock + BookmarkId mReadingListId; + @Mock + BookmarkItem mReadingListItem; + @Mock + BookmarkId mReadingListFolder; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + doReturn(mReadingListId).when(mReadingListItem).getId(); + doReturn(mReadingListItem).when(mBookmarkModel).getReadingListItem(any()); + doAnswer((invocation) -> { + ((Runnable) invocation.getArgument(0)).run(); + return null; + }) + .when(mBookmarkModel) + .finishLoadingBookmarkModel(any()); + doReturn(BookmarkType.NORMAL).when(mBookmarkId).getType(); + doReturn(BookmarkType.READING_LIST).when(mReadingListFolder).getType(); + doReturn(mReadingListFolder).when(mBookmarkModel).getReadingListFolder(); + doReturn(mBookmarkItem).when(mBookmarkModel).getBookmarkById(mBookmarkId); + doReturn(mReadingListId).when(mBookmarkModel).addToReadingList(any(), any()); + } + @Test @SmallTest - public void testIsReadingListSupport() { + public void isReadingListSupported() { Assert.assertFalse(ReadingListUtils.isReadingListSupported(null)); Assert.assertFalse(ReadingListUtils.isReadingListSupported(GURL.emptyGURL())); Assert.assertFalse(ReadingListUtils.isReadingListSupported( @@ -43,20 +86,104 @@ JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL))); Assert.assertTrue(ReadingListUtils.isReadingListSupported( JUnitTestGURLs.getGURL(JUnitTestGURLs.HTTP_URL))); + + // empty url + GURL testUrl = GURL.emptyGURL(); + Assert.assertFalse(ReadingListUtils.isReadingListSupported(testUrl)); + + // invalid url + Assert.assertFalse(ReadingListUtils.isReadingListSupported( + JUnitTestGURLs.getGURL(JUnitTestGURLs.INVALID_URL))); } - private void allowBookmarkTypeSwapping() { - TestValues readLaterTypeSwapping = new TestValues(); - readLaterTypeSwapping.addFeatureFlagOverride(ChromeFeatureList.READ_LATER, true); - readLaterTypeSwapping.addFieldTrialParamOverride( - ChromeFeatureList.READ_LATER, "allow_bookmark_type_swapping", "true"); - FeatureList.setTestValues(readLaterTypeSwapping); + @Test + @SmallTest + public void deleteFromReadingList() { + BookmarkModel bookmarkModel = Mockito.mock(BookmarkModel.class); + BookmarkId readingListId = Mockito.mock(BookmarkId.class); + BookmarkItem readingListItem = Mockito.mock(BookmarkItem.class); + doReturn(readingListId).when(readingListItem).getId(); + doReturn(readingListItem).when(bookmarkModel).getReadingListItem(any()); + doAnswer((invocation) -> { + ((Runnable) invocation.getArgument(0)).run(); + return null; + }) + .when(bookmarkModel) + .finishLoadingBookmarkModel(any()); + + ReadingListUtils.deleteFromReadingList(bookmarkModel, Mockito.mock(SnackbarManager.class), + Mockito.mock(Activity.class), Mockito.mock(Tab.class)); + verify(bookmarkModel).getReadingListItem(any()); + verify(bookmarkModel).deleteBookmarks(readingListId); + } + + @Test + @SmallTest + public void isSwappableReadingListItem() { + BookmarkId readingListId = new BookmarkId(1, BookmarkType.READING_LIST); + BookmarkId regularId = new BookmarkId(1, BookmarkType.NORMAL); + + // feature disabled + setBookmarkTypeSwappingEnabled(false); + Assert.assertFalse(ReadingListUtils.isSwappableReadingListItem(readingListId)); + + // wrong type + setBookmarkTypeSwappingEnabled(true); + Assert.assertFalse(ReadingListUtils.isSwappableReadingListItem(regularId)); + + setBookmarkTypeSwappingEnabled(true); + Assert.assertTrue(ReadingListUtils.isSwappableReadingListItem(readingListId)); + } + + @Test + @SmallTest + public void maybeTypeSwapAndShowSaveFlow() { + setBookmarkTypeSwappingEnabled(true); + ReadingListUtils.setSkipShowSaveFlowForTesting(true); + + Assert.assertTrue(ReadingListUtils.maybeTypeSwapAndShowSaveFlow( + Mockito.mock(Activity.class), Mockito.mock(BottomSheetController.class), + mBookmarkModel, mBookmarkId, BookmarkType.READING_LIST)); + verify(mBookmarkModel).addToReadingList(any(), any()); + } + + @Test + @SmallTest + public void maybeTypeSwapAndShowSaveFlow_EdgeCases() { + BookmarkId bookmarkId = Mockito.mock(BookmarkId.class); + doReturn(BookmarkType.NORMAL).when(bookmarkId).getType(); + + // feature disabled + setBookmarkTypeSwappingEnabled(false); + Assert.assertFalse(ReadingListUtils.maybeTypeSwapAndShowSaveFlow( + Mockito.mock(Activity.class), Mockito.mock(BottomSheetController.class), + Mockito.mock(BookmarkModel.class), bookmarkId, BookmarkType.READING_LIST)); + + // bookmarkId null + setBookmarkTypeSwappingEnabled(true); + Assert.assertFalse(ReadingListUtils.maybeTypeSwapAndShowSaveFlow( + Mockito.mock(Activity.class), Mockito.mock(BottomSheetController.class), + Mockito.mock(BookmarkModel.class), /*bookmarkId=*/null, BookmarkType.READING_LIST)); + + // bad original type + setBookmarkTypeSwappingEnabled(true); + doReturn(BookmarkType.READING_LIST).when(bookmarkId).getType(); + Assert.assertFalse(ReadingListUtils.maybeTypeSwapAndShowSaveFlow( + Mockito.mock(Activity.class), Mockito.mock(BottomSheetController.class), + Mockito.mock(BookmarkModel.class), bookmarkId, BookmarkType.READING_LIST)); + + // bad desired type + setBookmarkTypeSwappingEnabled(true); + doReturn(BookmarkType.NORMAL).when(bookmarkId).getType(); + Assert.assertFalse(ReadingListUtils.maybeTypeSwapAndShowSaveFlow( + Mockito.mock(Activity.class), Mockito.mock(BottomSheetController.class), + Mockito.mock(BookmarkModel.class), bookmarkId, BookmarkType.NORMAL)); } @Test @SmallTest public void testTypeSwapBookmarksIfNecessary_ToReadingList() { - allowBookmarkTypeSwapping(); + setBookmarkTypeSwappingEnabled(true); BookmarkId parentId = new BookmarkId(0, BookmarkType.READING_LIST); BookmarkId existingBookmarkId = new BookmarkId(0, BookmarkType.NORMAL); @@ -81,7 +208,7 @@ @Test @SmallTest public void testTypeSwapBookmarksIfNecessary_ToBookmark() { - allowBookmarkTypeSwapping(); + setBookmarkTypeSwappingEnabled(true); BookmarkId parentId = new BookmarkId(0, BookmarkType.NORMAL); BookmarkId existingBookmarkId = new BookmarkId(0, BookmarkType.READING_LIST); @@ -106,7 +233,7 @@ @Test @SmallTest public void testTypeSwapBookmarksIfNecessary_ToBookmark_Multiple() { - allowBookmarkTypeSwapping(); + setBookmarkTypeSwappingEnabled(true); BookmarkId parentId = new BookmarkId(0, BookmarkType.NORMAL); BookmarkId existingBookmarkId1 = new BookmarkId(1, BookmarkType.READING_LIST); @@ -147,7 +274,7 @@ @Test @SmallTest public void testTypeSwapBookmarksIfNecessary_TypeMatches() { - allowBookmarkTypeSwapping(); + setBookmarkTypeSwappingEnabled(true); BookmarkId parentId = new BookmarkId(0, BookmarkType.NORMAL); BookmarkId existingBookmarkId = new BookmarkId(0, BookmarkType.NORMAL); @@ -161,4 +288,12 @@ ReadingListUtils.typeSwapBookmarksIfNecessary(bookmarkBridge, bookmarks, parentId); Assert.assertEquals(existingBookmarkId, bookmarks.get(0)); } + + private void setBookmarkTypeSwappingEnabled(boolean enabled) { + TestValues readLaterTypeSwapping = new TestValues(); + readLaterTypeSwapping.addFeatureFlagOverride(ChromeFeatureList.READ_LATER, true); + readLaterTypeSwapping.addFieldTrialParamOverride(ChromeFeatureList.READ_LATER, + "allow_bookmark_type_swapping", enabled ? "true" : "false"); + FeatureList.setTestValues(readLaterTypeSwapping); + } }
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerFlowTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerFlowTest.java index a2202fe3..87da4cd01 100644 --- a/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerFlowTest.java +++ b/chrome/android/junit/src/org/chromium/chrome/browser/survey/ChromeSurveyControllerFlowTest.java
@@ -5,6 +5,8 @@ package org.chromium.chrome.browser.survey; import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; @@ -211,6 +213,7 @@ @After public void tearDown() { ChromeSurveyController.forceIsUMAEnabledForTesting(false); + ChromeSurveyController.resetMessageShownForTesting(); ShadowChromeFeatureList.sParamValues.clear(); ShadowChromeFeatureList.sEnableSurvey = false; ShadowChromeFeatureList.sEnableMessages = false; @@ -608,6 +611,17 @@ } @Test + public void testMessages_MessageShownOnce() { + presentMessages(); + Assert.assertTrue("Message should be shown.", ChromeSurveyController.isMessageShown()); + verify(mMessageDispatcher).enqueueMessage(any(), any(), anyInt(), anyBoolean()); + + // Simulate survey download that triggers invocation of #showSurveyPrompt. + mTestSurveyController.onDownloadSuccessRunnable.run(); + verifyNoMoreInteractions(mMessageDispatcher); + } + + @Test public void testMessages_Dismiss_PrimaryAction() { presentMessages(); PropertyModel messageModel = mMessagePropertyCaptor.getValue();
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp index 048a40bc..862e997 100644 --- a/chrome/app/chromeos_strings.grdp +++ b/chrome/app/chromeos_strings.grdp
@@ -4582,6 +4582,12 @@ <message name="IDS_CROSTINI_UPGRADER_BACKING_UP_MESSAGE" desc="Text shown by the Crostini upgrader when the container backup is in progress."> This may take up to 30 minutes. </message> + <message name="IDS_CROSTINI_UPGRADER_BACKUP_ERROR_TITLE" desc="Title of the Crostini upgrader when the container backup fails."> + Backing up failed + </message> + <message name="IDS_CROSTINI_UPGRADER_BACKUP_ERROR_MESSAGE" desc="Text shown by the Crostini upgrader when the container backup fails."> + Backing up Linux apps and files failed. This can happen if your device doesn't have enough free storage space. Try freeing some space on your device, or picking a different location to back up to. + </message> <message name="IDS_CROSTINI_UPGRADER_BACKUP_SUCCEEDED_TITLE" desc="Title of the Crostini upgrader when the container backup completed successfully, prior to the main upgrade."> Backing up complete </message> @@ -4615,6 +4621,12 @@ <message name="IDS_CROSTINI_UPGRADER_RESTORE_TITLE" desc="Title of the Crostini upgrader when the container upgrade fails and restore of a backup is in progress."> Restoring Linux </message> + <message name="IDS_CROSTINI_UPGRADER_RESTORE_ERROR_TITLE" desc="Title of the Crostini upgrader when restoring from backup fails."> + Restore failed + </message> + <message name="IDS_CROSTINI_UPGRADER_RESTORE_ERROR_MESSAGE" desc="Text shown by the Crostini upgrader when restoring from backup fails fails."> + Restoring your Linux backup failed. This may be because Linux doesn't have enough disk space. You can change how much disk space Linux has and try to restore your backup again in the OS Settings. + </message> <message name="IDS_CROSTINI_UPGRADER_RESTORE_SUCCEEDED_TITLE" desc="Title of the Crostini upgrader when the upgrade failed but the restore of a backup completed successfully."> Restore complete </message>
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_BACKUP_ERROR_MESSAGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_BACKUP_ERROR_MESSAGE.png.sha1 new file mode 100644 index 0000000..0c815b8 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_BACKUP_ERROR_MESSAGE.png.sha1
@@ -0,0 +1 @@ +de8a2730385f3a52fa474d3706f3de2a97251b52 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_BACKUP_ERROR_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_BACKUP_ERROR_TITLE.png.sha1 new file mode 100644 index 0000000..0c815b8 --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_BACKUP_ERROR_TITLE.png.sha1
@@ -0,0 +1 @@ +de8a2730385f3a52fa474d3706f3de2a97251b52 \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_RESTORE_ERROR_MESSAGE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_RESTORE_ERROR_MESSAGE.png.sha1 new file mode 100644 index 0000000..5a1098b --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_RESTORE_ERROR_MESSAGE.png.sha1
@@ -0,0 +1 @@ +6d4a6eb2cbfab9bdcc5135c22b66252815a039ae \ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_RESTORE_ERROR_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_RESTORE_ERROR_TITLE.png.sha1 new file mode 100644 index 0000000..5a1098b --- /dev/null +++ b/chrome/app/chromeos_strings_grdp/IDS_CROSTINI_UPGRADER_RESTORE_ERROR_TITLE.png.sha1
@@ -0,0 +1 @@ +6d4a6eb2cbfab9bdcc5135c22b66252815a039ae \ No newline at end of file
diff --git a/chrome/app/extensions_strings.grdp b/chrome/app/extensions_strings.grdp index b08840b..e1fad8de 100644 --- a/chrome/app/extensions_strings.grdp +++ b/chrome/app/extensions_strings.grdp
@@ -289,6 +289,9 @@ <message name="IDS_EXTENSIONS_ITEM_SITE_ACCESS_EMPTY" desc="The text to indicate that an extension does not have any site access."> This extension has no additional site access </message> + <message name="IDS_EXTENSIONS_REMOVE_SITES_DIALOG_TITLE" desc="The title for the dialog to warn the user when changing site access settings will clear the list of specific sites added."> + Remove the specific sites you added? + </message> <message name="IDS_EXTENSIONS_ITEM_SOURCE" desc="The label above an extension's source, which indicates where the extension came from (webstore, third-party, local disk, etc)."> Source </message>
diff --git a/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_REMOVE_SITES_DIALOG_TITLE.png.sha1 b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_REMOVE_SITES_DIALOG_TITLE.png.sha1 new file mode 100644 index 0000000..b512543 --- /dev/null +++ b/chrome/app/extensions_strings_grdp/IDS_EXTENSIONS_REMOVE_SITES_DIALOG_TITLE.png.sha1
@@ -0,0 +1 @@ +e6cc7aefd6274f38368f2f21c23ba35f6ee1861c \ No newline at end of file
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 783cf3f..e6feed73 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd
@@ -4713,6 +4713,15 @@ <message name="IDS_EXTENSION_ACTION_INSPECT_POPUP" desc="The text for the right-click menu of page and browser actions which shows the popup and opens the developer tools (sentence case)."> Inspect popup </message> + <message name="IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_CLICK" desc="The label in an extension's site access combobox to allow the extension access to the page only when the user click on the extension action (sentence case)."> + When I click the extension + </message> + <message name="IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_SITE" desc="The label in an extension's site access combobox to always allow the extension access to the current origin (sentence case)."> + Always + </message> + <message name="IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_ALL_SITES" desc="The label in an extension's site access combobox to always allow the extension access on all sites (sentence case)."> + Always on all sites + </message> </if> <if expr="use_titlecase"> <message name="IDS_EXTENSIONS_CONTEXT_MENU_CANT_ACCESS_PAGE" desc="The label in an extension's context menu indicating the extension cannot access the current page. (title case)"> @@ -4769,6 +4778,15 @@ <message name="IDS_EXTENSION_ACTION_INSPECT_POPUP" desc="The text for the right-click menu of page and browser actions which shows the popup and opens the developer tools (title case)."> Inspect Popup </message> + <message name="IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_CLICK" desc="The label in an extension's site access combobox to allow the extension access to the page only when the user click on the extension action (title case)."> + When I Click the Extension + </message> + <message name="IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_SITE" desc="The label in an extension's site access combobox to always allow the extension access to the current origin (title case)."> + Always + </message> + <message name="IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_ALL_SITES" desc="The label in an extension's site access combobox to always allow the extension access on all sites (title case)."> + Always on All Sites + </message> </if> </if> @@ -6587,6 +6605,9 @@ <message name="IDS_ACCNAME_MUTE_TAB" desc="The accessible name for the Mute tab button."> Mute tab </message> + <message name="IDS_ACCNAME_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX" desc="The accessible name for the extension's site access combobox in the extensions menu."> + Site Access Option + </message> <!-- Clipboard permission --> <message name="IDS_ALLOWED_CLIPBOARD_TITLE" desc="Title of the info bubble shown when a site has been allowed access to read the contents of the system clipboard."> @@ -11148,13 +11169,29 @@ "<ph name="CHROME_EXTENSION_NAME">$1<ex>Chrome Extension Name</ex></ph>" wants to connect to a HID device </message> <message name="IDS_HID_CHOOSER_ITEM_WITHOUT_NAME" desc="User option displaying the device IDs for a Human Interface Device (HID) without a device name."> - Unknown Device (<ph name="DEVICE_ID">$1<ex>1234:abcd</ex></ph>) </message> + Unknown Device (<ph name="DEVICE_ID">$1<ex>1234:abcd</ex></ph>) + </message> <message name="IDS_HID_CHOOSER_LOADING_LABEL" desc="Text on label that the browser is loading the list of HID devices."> Finding devices... </message> <message name="IDS_HID_CHOOSER_LOADING_LABEL_TOOLTIP" desc="Tooltip for the label that the browser is loading the list of HID devices."> Finding HID devices... </message> + <message name="IDS_HID_POLICY_DESCRIPTION_FOR_VENDOR_ID_AND_PRODUCT_ID" desc="String describing a HID device permission granted by enterprise policy to a site when only the numeric product ID and vendor ID are available"> + HID device (<ph name="VENDOR_ID">$1<ex>1234</ex></ph>:<ph name="PRODUCT_ID">$2<ex>1234</ex></ph>) + </message> + <message name="IDS_HID_POLICY_DESCRIPTION_FOR_VENDOR_ID" desc="String describing a HID device permission granted by enterprise policy to a site for all devices from a single vendor when only the numeric vendor ID is available."> + HID devices from vendor <ph name="VENDOR_ID">$1<ex>1234</ex></ph> + </message> + <message name="IDS_HID_POLICY_DESCRIPTION_FOR_USAGE_AND_USAGE_PAGE" desc="String describing a HID device permission granted by permission policy to a site for all devices containing a top-level collection with a single HID usage when only the numeric HID usage value is available."> + HID devices with usage <ph name="USAGE">$1<ex>1234</ex></ph> from usage page <ph name="USAGE_PAGE">$2<ex>1234</ex></ph> + </message> + <message name="IDS_HID_POLICY_DESCRIPTION_FOR_USAGE_PAGE" desc="String describing a HID device permission granted by permission policy to a site for all devices containing a top-level collection with any usage from a HID usage page when only the numeric HID usage page value is available."> + HID devices with usages from usage page <ph name="USAGE_PAGE">$1<ex>1234</ex></ph> + </message> + <message name="IDS_HID_POLICY_DESCRIPTION_FOR_ANY_DEVICE" desc="String describing a HID device permission granted by permission policy to a site for all devices."> + Any HID device + </message> </if> <!-- File Handling launch prompt -->
diff --git a/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_ALL_SITES.png.sha1 b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_ALL_SITES.png.sha1 new file mode 100644 index 0000000..a768f20 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_ALL_SITES.png.sha1
@@ -0,0 +1 @@ +c7f39547506384b314958a9187542493e62aab00 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_CLICK.png.sha1 b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_CLICK.png.sha1 new file mode 100644 index 0000000..af7d49e --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_CLICK.png.sha1
@@ -0,0 +1 @@ +e94d12839ce3cbf5c5b23afb7c44b66666ae2341 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_SITE.png.sha1 b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_SITE.png.sha1 new file mode 100644 index 0000000..00572f1 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_SITE.png.sha1
@@ -0,0 +1 @@ +e5ac077f08987bf931d7638bfc61f04b10ef351e \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_ANY_DEVICE.png.sha1 b/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_ANY_DEVICE.png.sha1 new file mode 100644 index 0000000..2982545 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_ANY_DEVICE.png.sha1
@@ -0,0 +1 @@ +08a6fd37d6ce1c9525bd576b24e739082fc6fdef \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_USAGE_AND_USAGE_PAGE.png.sha1 b/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_USAGE_AND_USAGE_PAGE.png.sha1 new file mode 100644 index 0000000..720d21c --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_USAGE_AND_USAGE_PAGE.png.sha1
@@ -0,0 +1 @@ +e433757f06611e4604829a948bde13fb2830fdc2 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_USAGE_PAGE.png.sha1 b/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_USAGE_PAGE.png.sha1 new file mode 100644 index 0000000..36d51a4 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_USAGE_PAGE.png.sha1
@@ -0,0 +1 @@ +a804deb2606f84a951b47ee0c85a4ceb63f4c0a9 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_VENDOR_ID.png.sha1 b/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_VENDOR_ID.png.sha1 new file mode 100644 index 0000000..efcbc6fb --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_VENDOR_ID.png.sha1
@@ -0,0 +1 @@ +13bef1094a712e95babd8c7bae535f2d230cdb90 \ No newline at end of file
diff --git a/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_VENDOR_ID_AND_PRODUCT_ID.png.sha1 b/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_VENDOR_ID_AND_PRODUCT_ID.png.sha1 new file mode 100644 index 0000000..7455e10 --- /dev/null +++ b/chrome/app/generated_resources_grd/IDS_HID_POLICY_DESCRIPTION_FOR_VENDOR_ID_AND_PRODUCT_ID.png.sha1
@@ -0,0 +1 @@ +a71bbeff7f63a7af115d4b51d9eb3b90c5f5adee \ No newline at end of file
diff --git a/chrome/app/os_settings_strings.grdp b/chrome/app/os_settings_strings.grdp index c7aa2d6..534312e1 100644 --- a/chrome/app/os_settings_strings.grdp +++ b/chrome/app/os_settings_strings.grdp
@@ -2079,6 +2079,15 @@ <message name="IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_RIGHT_BUD_BATTERY_PERCENTAGE_A11Y_LABEL" desc="Bluetooth device details page: A11y label informing the current battery percentage of the right true wireless bud."> Right battery level <ph name="PERCENTAGE">$1<ex>90</ex></ph>%. </message> + <message name="IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_LEFT_BUD_LABEL" desc="Bluetooth True Wireless Images component: Label describing the left bud of a set of True Wireless headphones."> + Left + </message> + <message name="IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_CASE_LABEL" desc="Bluetooth True Wireless Images component: Label describing the case of a set of True Wireless headphones."> + Case + </message> + <message name="IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_RIGHT_BUD_LABEL" desc="Bluetooth True Wireless Images component: Label describing the right bud of a set of True Wireless headphones."> + Right + </message> <message name="IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CONNECTED_A11Y_LABEL" desc="Bluetooth device details page: A11y label informing the current device is connected."> Connected to <ph name="DEVICE">$1<ex>Beats</ex></ph> </message>
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_CASE_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_CASE_LABEL.png.sha1 new file mode 100644 index 0000000..c832ca0 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_CASE_LABEL.png.sha1
@@ -0,0 +1 @@ +020d13affa6882c99f90adb838a7dcab29ed83a5 \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_LEFT_BUD_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_LEFT_BUD_LABEL.png.sha1 new file mode 100644 index 0000000..384aa0911 --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_LEFT_BUD_LABEL.png.sha1
@@ -0,0 +1 @@ +4fe38c81ec1153adf6306d7a38398fcad103051a \ No newline at end of file
diff --git a/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_RIGHT_BUD_LABEL.png.sha1 b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_RIGHT_BUD_LABEL.png.sha1 new file mode 100644 index 0000000..b256fec --- /dev/null +++ b/chrome/app/os_settings_strings_grdp/IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_RIGHT_BUD_LABEL.png.sha1
@@ -0,0 +1 @@ +7e1527e33c5d1dd453b6c45e9dd9030670fa8d0f \ No newline at end of file
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index ecf5342..0eca083 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4212,10 +4212,6 @@ flag_descriptions::kAriaElementReflectionDescription, kOsAll, FEATURE_VALUE_TYPE(features::kEnableAriaElementReflection)}, #if BUILDFLAG(IS_CHROMEOS_ASH) - {"enable-cros-ime-assist-autocorrect", - flag_descriptions::kImeAssistAutocorrectName, - flag_descriptions::kImeAssistAutocorrectDescription, kOsCrOS, - FEATURE_VALUE_TYPE(chromeos::features::kAssistAutoCorrect)}, {"enable-cros-ime-assist-emoji-enhanced", flag_descriptions::kImeAssistEmojiEnhancedName, flag_descriptions::kImeAssistEmojiEnhancedDescription, kOsCrOS, @@ -4240,10 +4236,6 @@ flag_descriptions::kVirtualKeyboardDarkModeName, flag_descriptions::kVirtualKeyboardDarkModeDescription, kOsCrOS, FEATURE_VALUE_TYPE(chromeos::features::kVirtualKeyboardDarkMode)}, - {"enable-cros-ime-system-emoji-picker", - flag_descriptions::kImeSystemEmojiPickerName, - flag_descriptions::kImeSystemEmojiPickerDescription, kOsCrOS, - FEATURE_VALUE_TYPE(chromeos::features::kImeSystemEmojiPicker)}, {"enable-cros-ime-system-emoji-picker-clipboard", flag_descriptions::kImeSystemEmojiPickerClipboardName, flag_descriptions::kImeSystemEmojiPickerClipboardDescription, kOsCrOS, @@ -4260,10 +4252,6 @@ flag_descriptions::kCrosLanguageSettingsUpdate2Name, flag_descriptions::kCrosLanguageSettingsUpdate2Description, kOsCrOS, FEATURE_VALUE_TYPE(chromeos::features::kLanguageSettingsUpdate2)}, - {"enable-cros-language-settings-ime-options-in-settings", - flag_descriptions::kCrosLanguageSettingsImeOptionsInSettingsName, - flag_descriptions::kCrosLanguageSettingsImeOptionsInSettingsDescription, - kOsCrOS, FEATURE_VALUE_TYPE(chromeos::features::kImeOptionsInSettings)}, {"enable-cros-multilingual-typing", flag_descriptions::kMultilingualTypingName, flag_descriptions::kMultilingualTypingDescription, kOsCrOS, @@ -4532,6 +4520,9 @@ {"fuse-box", flag_descriptions::kFuseBoxName, flag_descriptions::kFuseBoxDescription, kOsCrOS, FEATURE_VALUE_TYPE(chromeos::features::kFuseBox)}, + {"guest-os-files", flag_descriptions::kGuestOsFilesName, + flag_descriptions::kGuestOsFilesDescription, kOsCrOS, + FEATURE_VALUE_TYPE(chromeos::features::kGuestOsFiles)}, {"spectre-v2-mitigation", flag_descriptions::kSpectreVariant2MitigationName, flag_descriptions::kSpectreVariant2MitigationDescription, kOsCrOS, FEATURE_VALUE_TYPE(sandbox::policy::features::kSpectreVariant2Mitigation)}, @@ -4924,7 +4915,7 @@ flag_descriptions::kReadLaterDescription, kOsAndroid, FEATURE_WITH_PARAMS_VALUE_TYPE(reading_list::switches::kReadLater, kReadLaterVariations, - "ReadLater")}, + "Collections")}, #else {flag_descriptions::kReadLaterFlagId, flag_descriptions::kReadLaterName, flag_descriptions::kReadLaterDescription, kOsDesktop, @@ -5423,13 +5414,6 @@ network::switches::kUnsafelyTreatInsecureOriginAsSecure, "")}, - {"detect-target-embedding-lookalikes", - flag_descriptions::kDetectTargetEmbeddingLookalikesName, - flag_descriptions::kDetectTargetEmbeddingLookalikesDescription, - kOsDesktop | kOsAndroid, - FEATURE_VALUE_TYPE( - lookalikes::features::kDetectTargetEmbeddingLookalikes)}, - {"disable-process-reuse", flag_descriptions::kDisableProcessReuse, flag_descriptions::kDisableProcessReuseDescription, kOsDesktop, FEATURE_VALUE_TYPE(features::kDisableProcessReuse)}, @@ -5688,13 +5672,6 @@ #endif #if BUILDFLAG(IS_CHROMEOS_ASH) - {"app-management-intent-settings", - flag_descriptions::kAppManagementIntentSettingsName, - flag_descriptions::kAppManagementIntentSettingsDescription, kOsCrOS, - FEATURE_VALUE_TYPE(features::kAppManagementIntentSettings)}, -#endif - -#if BUILDFLAG(IS_CHROMEOS_ASH) {"arc-ghost-window", flag_descriptions::kArcGhostWindowName, flag_descriptions::kArcGhostWindowDescription, kOsCrOS, FEATURE_VALUE_TYPE(full_restore::features::kArcGhostWindow)}, @@ -7280,15 +7257,6 @@ FEATURE_VALUE_TYPE(chromeos::features::kLauncherAppSort)}, #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ - BUILDFLAG(IS_FUCHSIA) - {"enable-desktop-pwas-app-icon-shortcuts-menu-ui", - flag_descriptions::kDesktopPWAsAppIconShortcutsMenuUIName, - flag_descriptions::kDesktopPWAsAppIconShortcutsMenuUIDescription, - kOsCrOS | kOsMac | kOsLinux | kOsFuchsia, - FEATURE_VALUE_TYPE(features::kDesktopPWAsAppIconShortcutsMenuUI)}, -#endif - #if BUILDFLAG(IS_CHROMEOS_ASH) {"enable-input-event-logging", flag_descriptions::kEnableInputEventLoggingName, @@ -7410,10 +7378,6 @@ FEATURE_VALUE_TYPE(::features::kFocusFollowsCursor)}, #endif // BUILDFLAG(IS_CHROMEOS_ASH) - {"clipboard-custom-formats", flag_descriptions::kClipboardCustomFormatsName, - flag_descriptions::kClipboardCustomFormatsDescription, kOsAll, - FEATURE_VALUE_TYPE(blink::features::kClipboardCustomFormats)}, - #if BUILDFLAG(IS_CHROMEOS_ASH) {"performant-split-view-resizing", flag_descriptions::kPerformantSplitViewResizing, @@ -7625,7 +7589,7 @@ flag_descriptions::kBookmarksRefreshDescription, kOsAndroid, FEATURE_WITH_PARAMS_VALUE_TYPE(chrome::android::kBookmarksRefresh, kBookmarksRefreshVariations, - "BookmarksRefresh")}, + "Collections")}, #endif {"enable-tab-audio-muting", flag_descriptions::kTabAudioMutingName,
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc index d067528..a2c7084 100644 --- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc +++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.cc
@@ -23,6 +23,7 @@ : SceneLayer(env, jobj), tab_strip_layer_(cc::SolidColorLayer::Create()), scrollable_strip_layer_(cc::Layer::Create()), + scrim_layer_(cc::SolidColorLayer::Create()), new_tab_button_(cc::UIResourceLayer::Create()), left_fade_(cc::UIResourceLayer::Create()), right_fade_(cc::UIResourceLayer::Create()), @@ -35,6 +36,7 @@ model_selector_button_->SetIsDrawable(true); left_fade_->SetIsDrawable(true); right_fade_->SetIsDrawable(true); + scrim_layer_->SetIsDrawable(true); // When the ScrollingStripStacker is used, the new tab button and tabs scroll, // while the incognito button and left/ride fade stay fixed. Put the new tab @@ -45,6 +47,8 @@ tab_strip_layer_->SetBackgroundColor(SK_ColorBLACK); tab_strip_layer_->SetIsDrawable(true); tab_strip_layer_->AddChild(scrollable_strip_layer_); + + tab_strip_layer_->AddChild(scrim_layer_); tab_strip_layer_->AddChild(left_fade_); tab_strip_layer_->AddChild(right_fade_); tab_strip_layer_->AddChild(model_selector_button_); @@ -137,6 +141,26 @@ } } +void TabStripSceneLayer::UpdateStripScrim(JNIEnv* env, + const JavaParamRef<jobject>& jobj, + jfloat x, + jfloat y, + jfloat width, + jfloat height, + jint color, + jfloat alpha) { + if (alpha == 0.f) { + scrim_layer_->SetIsDrawable(false); + return; + } + + scrim_layer_->SetIsDrawable(true); + scrim_layer_->SetBackgroundColor(color); + scrim_layer_->SetBounds(gfx::Size(width, height)); + scrim_layer_->SetPosition(gfx::PointF(x, y)); + scrim_layer_->SetOpacity(alpha); +} + void TabStripSceneLayer::UpdateNewTabButton( JNIEnv* env, const JavaParamRef<jobject>& jobj,
diff --git a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h index 183accb..a0963be 100644 --- a/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h +++ b/chrome/browser/android/compositor/scene_layer/tab_strip_scene_layer.h
@@ -57,6 +57,15 @@ jfloat brightness, jboolean should_readd_background); + void UpdateStripScrim(JNIEnv* env, + const base::android::JavaParamRef<jobject>& jobj, + jfloat x, + jfloat y, + jfloat width, + jfloat height, + jint color, + jfloat alpha); + void UpdateNewTabButton( JNIEnv* env, const base::android::JavaParamRef<jobject>& jobj, @@ -129,6 +138,7 @@ scoped_refptr<cc::SolidColorLayer> tab_strip_layer_; scoped_refptr<cc::Layer> scrollable_strip_layer_; + scoped_refptr<cc::SolidColorLayer> scrim_layer_; scoped_refptr<cc::UIResourceLayer> new_tab_button_; scoped_refptr<cc::UIResourceLayer> left_fade_; scoped_refptr<cc::UIResourceLayer> right_fade_;
diff --git a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc index 685dd5aa..b7206cbc 100644 --- a/chrome/browser/android/contextualsearch/contextual_search_delegate.cc +++ b/chrome/browser/android/contextualsearch/contextual_search_delegate.cc
@@ -552,12 +552,9 @@ // Extract an arbitrary Related Searches payload as JSON and return to Java // for decoding. // TODO(donnd): remove soon (once the server is updated); - if (dict->HasKey(kRelatedSearchesSuggestions)) { - base::Value* rsearches_json_value = nullptr; - dict->Get(kRelatedSearchesSuggestions, &rsearches_json_value); - DCHECK(rsearches_json_value); + if (base::Value* rsearches_json_value = + dict->FindKey(kRelatedSearchesSuggestions)) base::JSONWriter::Write(*rsearches_json_value, related_searches_json); - } } // Extract the Start/End of the mentions in the surrounding text
diff --git a/chrome/browser/android/hung_renderer_infobar_delegate.cc b/chrome/browser/android/hung_renderer_infobar_delegate.cc index a772a90..3af5aa23a2 100644 --- a/chrome/browser/android/hung_renderer_infobar_delegate.cc +++ b/chrome/browser/android/hung_renderer_infobar_delegate.cc
@@ -25,29 +25,17 @@ new HungRendererInfoBarDelegate(render_process_host)))); } -void HungRendererInfoBarDelegate::OnRendererResponsive() { - LogEvent(RENDERER_BECAME_RESPONSIVE); -} - HungRendererInfoBarDelegate::HungRendererInfoBarDelegate( content::RenderProcessHost* render_process_host) - : render_process_host_(render_process_host), - terminal_event_logged_for_uma_(false) {} + : render_process_host_(render_process_host) {} -HungRendererInfoBarDelegate::~HungRendererInfoBarDelegate() { - if (!terminal_event_logged_for_uma_) - LogEvent(TAB_CLOSED); -} +HungRendererInfoBarDelegate::~HungRendererInfoBarDelegate() = default; infobars::InfoBarDelegate::InfoBarIdentifier HungRendererInfoBarDelegate::GetIdentifier() const { return HUNG_RENDERER_INFOBAR_DELEGATE_ANDROID; } -void HungRendererInfoBarDelegate::InfoBarDismissed() { - LogEvent(CLOSE_CLICKED); -} - HungRendererInfoBarDelegate* HungRendererInfoBarDelegate::AsHungRendererInfoBarDelegate() { return this; @@ -69,19 +57,10 @@ } bool HungRendererInfoBarDelegate::Accept() { - LogEvent(KILL_CLICKED); render_process_host_->Shutdown(content::RESULT_CODE_HUNG); return true; } bool HungRendererInfoBarDelegate::Cancel() { - LogEvent(WAIT_CLICKED); return true; } - -void HungRendererInfoBarDelegate::LogEvent(Event event) { - DCHECK(!terminal_event_logged_for_uma_); - terminal_event_logged_for_uma_ = true; - UMA_HISTOGRAM_ENUMERATION("Renderer.Hung.MobileInfoBar.UserEvent", event, - EVENT_COUNT); -}
diff --git a/chrome/browser/android/hung_renderer_infobar_delegate.h b/chrome/browser/android/hung_renderer_infobar_delegate.h index b356038..033051b 100644 --- a/chrome/browser/android/hung_renderer_infobar_delegate.h +++ b/chrome/browser/android/hung_renderer_infobar_delegate.h
@@ -34,10 +34,6 @@ HungRendererInfoBarDelegate& operator=(const HungRendererInfoBarDelegate&) = delete; - // Called if the renderer regains responsiveness before the infobar is - // dismissed. - void OnRendererResponsive(); - private: // Keep these values in alignment with their histograms.xml counterparts. enum Event { @@ -55,7 +51,6 @@ // ConfirmInfoBarDelegate: infobars::InfoBarDelegate::InfoBarIdentifier GetIdentifier() const override; - void InfoBarDismissed() override; HungRendererInfoBarDelegate* AsHungRendererInfoBarDelegate() override; int GetIconId() const override; std::u16string GetMessageText() const override; @@ -63,12 +58,8 @@ bool Accept() override; bool Cancel() override; - void LogEvent(Event event); - // Used to terminate the renderer process if the user clicks the kill button. raw_ptr<content::RenderProcessHost> render_process_host_; - - bool terminal_event_logged_for_uma_; }; #endif // CHROME_BROWSER_ANDROID_HUNG_RENDERER_INFOBAR_DELEGATE_H_
diff --git a/chrome/browser/android/tab_web_contents_delegate_android.cc b/chrome/browser/android/tab_web_contents_delegate_android.cc index 96e740f..22517fc 100644 --- a/chrome/browser/android/tab_web_contents_delegate_android.cc +++ b/chrome/browser/android/tab_web_contents_delegate_android.cc
@@ -656,9 +656,6 @@ if (!hung_renderer_infobar) return; - hung_renderer_infobar->delegate() - ->AsHungRendererInfoBarDelegate() - ->OnRendererResponsive(); infobar_manager->RemoveInfoBar(hung_renderer_infobar); }
diff --git a/chrome/browser/apps/app_service/app_notifications.cc b/chrome/browser/apps/app_service/app_notifications.cc index 111f0ec..c4887e0 100644 --- a/chrome/browser/apps/app_service/app_notifications.cc +++ b/chrome/browser/apps/app_service/app_notifications.cc
@@ -61,10 +61,10 @@ return it->second; } -std::unique_ptr<App> AppNotifications::CreateAppWithHasBadgeStatus( +AppPtr AppNotifications::CreateAppWithHasBadgeStatus( AppType app_type, const std::string& app_id) { - std::unique_ptr<App> app = std::make_unique<App>(app_type, app_id); + auto app = std::make_unique<App>(app_type, app_id); app->has_badge = HasNotification(app_id); return app; }
diff --git a/chrome/browser/apps/app_service/app_notifications.h b/chrome/browser/apps/app_service/app_notifications.h index 3ee90ce..b2c5fdd 100644 --- a/chrome/browser/apps/app_service/app_notifications.h +++ b/chrome/browser/apps/app_service/app_notifications.h
@@ -44,8 +44,8 @@ std::set<std::string> GetAppIdsForNotification( const std::string& notification_id); - std::unique_ptr<App> CreateAppWithHasBadgeStatus(AppType app_type, - const std::string& app_id); + AppPtr CreateAppWithHasBadgeStatus(AppType app_type, + const std::string& app_id); apps::mojom::AppPtr GetAppWithHasBadgeStatus(apps::mojom::AppType app_type, const std::string& app_id);
diff --git a/chrome/browser/apps/app_service/app_service_proxy_base.cc b/chrome/browser/apps/app_service/app_service_proxy_base.cc index 22f7b25ad..a162dad 100644 --- a/chrome/browser/apps/app_service/app_service_proxy_base.cc +++ b/chrome/browser/apps/app_service/app_service_proxy_base.cc
@@ -590,33 +590,20 @@ return; } -#if BUILDFLAG(IS_CHROMEOS_ASH) - // Link capturing behavior is changing with the launch of this feature so that - // link capturing is enabled on a per app (rather than per-intent-filter) - // basis. Non-Chrome OS platforms do not currently use persistent link - // capturing preferences and so this is not a breaking change for them. - bool supported_links_behavior_enabled = - base::FeatureList::IsEnabled(features::kAppManagementIntentSettings); -#else - bool supported_links_behavior_enabled = true; -#endif + // Treat kUseBrowserForLink like an app with a single supported link, so + // that any apps with overlapping supported links will have their preference + // removed correctly. + if (app_id == apps::kUseBrowserForLink) { + std::vector<apps::mojom::IntentFilterPtr> filters; + filters.push_back(std::move(intent_filter)); + app_service_->SetSupportedLinksPreference(apps::mojom::AppType::kUnknown, + app_id, std::move(filters)); + return; + } - if (supported_links_behavior_enabled) { - // Treat kUseBrowserForLink like an app with a single supported link, so - // that any apps with overlapping supported links will have their preference - // removed correctly. - if (app_id == apps::kUseBrowserForLink) { - std::vector<apps::mojom::IntentFilterPtr> filters; - filters.push_back(std::move(intent_filter)); - app_service_->SetSupportedLinksPreference(apps::mojom::AppType::kUnknown, - app_id, std::move(filters)); - return; - } - - if (apps_util::IsSupportedLinkForApp(app_id, intent_filter)) { - SetSupportedLinksPreference(app_id); - return; - } + if (apps_util::IsSupportedLinkForApp(app_id, intent_filter)) { + SetSupportedLinksPreference(app_id); + return; } preferred_apps_.AddPreferredApp(app_id, intent_filter); @@ -664,8 +651,8 @@ } } -void AppServiceProxyBase::OnApps(std::vector<std::unique_ptr<apps::App>> deltas, - apps::AppType app_type, +void AppServiceProxyBase::OnApps(std::vector<AppPtr> deltas, + AppType app_type, bool should_notify_initialized) { // TODO(crbug.com/1253250): add RemovePreferredApp related code. app_registry_cache_.OnApps(std::move(deltas), app_type,
diff --git a/chrome/browser/apps/app_service/app_service_proxy_base.h b/chrome/browser/apps/app_service/app_service_proxy_base.h index d5fb67a..9052a1d0 100644 --- a/chrome/browser/apps/app_service/app_service_proxy_base.h +++ b/chrome/browser/apps/app_service/app_service_proxy_base.h
@@ -252,8 +252,8 @@ apps::mojom::WindowMode window_mode); // Called by an app publisher to inform the proxy of a change in app state. - void OnApps(std::vector<std::unique_ptr<apps::App>> deltas, - apps::AppType app_type, + void OnApps(std::vector<AppPtr> deltas, + AppType app_type, bool should_notify_initialized); protected:
diff --git a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc index cd940bfc..e65f0ddd 100644 --- a/chrome/browser/apps/app_service/app_service_proxy_unittest.cc +++ b/chrome/browser/apps/app_service/app_service_proxy_unittest.cc
@@ -30,7 +30,6 @@ #include "ui/gfx/image/image_skia_rep.h" #if BUILDFLAG(IS_CHROMEOS_ASH) -#include "base/test/scoped_feature_list.h" #include "chrome/common/chrome_features.h" #endif @@ -284,11 +283,6 @@ class AppServiceProxyPreferredAppsTest : public AppServiceProxyTest { public: void SetUp() override { -#if BUILDFLAG(IS_CHROMEOS_ASH) - scoped_feature_list_.InitAndEnableFeature( - features::kAppManagementIntentSettings); -#endif - proxy_ = AppServiceProxyFactory::GetForProfile(&profile_); auto* const provider = web_app::FakeWebAppProvider::Get(&profile_); @@ -305,10 +299,6 @@ } private: -#if BUILDFLAG(IS_CHROMEOS_ASH) - base::test::ScopedFeatureList scoped_feature_list_; -#endif - TestingProfile profile_; raw_ptr<AppServiceProxy> proxy_; };
diff --git a/chrome/browser/apps/app_service/paused_apps.cc b/chrome/browser/apps/app_service/paused_apps.cc index 680a001..57635e85 100644 --- a/chrome/browser/apps/app_service/paused_apps.cc +++ b/chrome/browser/apps/app_service/paused_apps.cc
@@ -25,11 +25,10 @@ return app; } -std::unique_ptr<App> PausedApps::CreateAppWithPauseStatus( - AppType app_type, - const std::string& app_id, - bool paused) { - std::unique_ptr<App> app = std::make_unique<App>(app_type, app_id); +AppPtr PausedApps::CreateAppWithPauseStatus(AppType app_type, + const std::string& app_id, + bool paused) { + auto app = std::make_unique<App>(app_type, app_id); app->paused = paused; return app; }
diff --git a/chrome/browser/apps/app_service/paused_apps.h b/chrome/browser/apps/app_service/paused_apps.h index bed435f..edfade31 100644 --- a/chrome/browser/apps/app_service/paused_apps.h +++ b/chrome/browser/apps/app_service/paused_apps.h
@@ -29,9 +29,9 @@ const std::string& app_id, bool paused); - std::unique_ptr<App> CreateAppWithPauseStatus(AppType app_type, - const std::string& app_id, - bool paused); + AppPtr CreateAppWithPauseStatus(AppType app_type, + const std::string& app_id, + bool paused); // Returns true if the app was added to the paused set, and false if it was // already there.
diff --git a/chrome/browser/apps/app_service/publishers/app_publisher.cc b/chrome/browser/apps/app_service/publishers/app_publisher.cc index 569d66d..856fb5c6 100644 --- a/chrome/browser/apps/app_service/publishers/app_publisher.cc +++ b/chrome/browser/apps/app_service/publishers/app_publisher.cc
@@ -15,13 +15,13 @@ AppPublisher::~AppPublisher() = default; // static -std::unique_ptr<App> AppPublisher::MakeApp(AppType app_type, - const std::string& app_id, - Readiness readiness, - const std::string& name, - InstallReason install_reason, - InstallSource install_source) { - std::unique_ptr<App> app = std::make_unique<App>(app_type, app_id); +AppPtr AppPublisher::MakeApp(AppType app_type, + const std::string& app_id, + Readiness readiness, + const std::string& name, + InstallReason install_reason, + InstallSource install_source) { + auto app = std::make_unique<App>(app_type, app_id); app->readiness = readiness; app->name = name; app->short_name = name; @@ -41,19 +41,19 @@ proxy_->RegisterPublisher(app_type, this); } -void AppPublisher::Publish(std::unique_ptr<App> app) { +void AppPublisher::Publish(AppPtr app) { if (!proxy_) { NOTREACHED(); return; } - std::vector<std::unique_ptr<App>> apps; + std::vector<AppPtr> apps; apps.push_back(std::move(app)); proxy_->OnApps(std::move(apps), apps::AppType::kUnknown, false /* should_notify_initialized */); } -void AppPublisher::Publish(std::vector<std::unique_ptr<App>> apps) { +void AppPublisher::Publish(std::vector<AppPtr> apps) { if (!proxy_) { NOTREACHED(); return;
diff --git a/chrome/browser/apps/app_service/publishers/app_publisher.h b/chrome/browser/apps/app_service/publishers/app_publisher.h index 17b3b2f5..a09f669 100644 --- a/chrome/browser/apps/app_service/publishers/app_publisher.h +++ b/chrome/browser/apps/app_service/publishers/app_publisher.h
@@ -31,12 +31,12 @@ ~AppPublisher(); // Returns an app object from the provided parameters - static std::unique_ptr<App> MakeApp(AppType app_type, - const std::string& app_id, - Readiness readiness, - const std::string& name, - InstallReason install_reason, - InstallSource install_source); + static AppPtr MakeApp(AppType app_type, + const std::string& app_id, + Readiness readiness, + const std::string& name, + InstallReason install_reason, + InstallSource install_source); // Registers this AppPublisher to AppServiceProxy, allowing it to receive App // Service API calls. This function must be called after the object's @@ -82,13 +82,13 @@ // represented by `app` undergoes some state change to inform AppServiceProxy // of the change. Ensure that RegisterPublisher() has been called before the // first call to this method. - void Publish(std::unique_ptr<App> app); + void Publish(AppPtr app); // Publish multiple `apps` to AppServiceProxy. Should be called whenever the // app represented by `app` undergoes some state change to inform // AppServiceProxy of the change. Ensure that RegisterPublisher() has been // called before the first call to this method. - void Publish(std::vector<std::unique_ptr<App>> apps); + void Publish(std::vector<AppPtr> apps); AppServiceProxy* proxy() { return proxy_; }
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps.cc b/chrome/browser/apps/app_service/publishers/arc_apps.cc index e4fdf1ed..ade3412 100644 --- a/chrome/browser/apps/app_service/publishers/arc_apps.cc +++ b/chrome/browser/apps/app_service/publishers/arc_apps.cc
@@ -609,7 +609,7 @@ RegisterPublisher(AppType::kArc); - std::vector<std::unique_ptr<App>> apps; + std::vector<AppPtr> apps; for (const auto& app_id : prefs->GetAppIds()) { std::unique_ptr<ArcAppListPrefs::AppInfo> app_info = prefs->GetApp(app_id); if (app_info) { @@ -1216,7 +1216,7 @@ mojom_app->readiness = apps::mojom::Readiness::kUninstalledByUser; PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = std::make_unique<App>(AppType::kArc, app_id); + auto app = std::make_unique<App>(AppType::kArc, app_id); app->readiness = Readiness::kUninstalledByUser; AppPublisher::Publish(std::move(app)); } @@ -1234,7 +1234,7 @@ mojom_app->name = name; PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = std::make_unique<App>(AppType::kArc, app_id); + auto app = std::make_unique<App>(AppType::kArc, app_id); app->name = name; AppPublisher::Publish(std::move(app)); } @@ -1254,7 +1254,7 @@ mojom_app->last_launch_time = app_info->last_launch_time; PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = std::make_unique<App>(AppType::kArc, app_id); + auto app = std::make_unique<App>(AppType::kArc, app_id); app->last_launch_time = app_info->last_launch_time; AppPublisher::Publish(std::move(app)); } @@ -1541,14 +1541,13 @@ return apps::mojom::InstallReason::kUser; } -std::unique_ptr<App> ArcApps::CreateApp( - ArcAppListPrefs* prefs, - const std::string& app_id, - const ArcAppListPrefs::AppInfo& app_info, - bool update_icon) { +AppPtr ArcApps::CreateApp(ArcAppListPrefs* prefs, + const std::string& app_id, + const ArcAppListPrefs::AppInfo& app_info, + bool update_icon) { auto install_reason = ConvertMojomInstallReasonToInstallReason( GetInstallReason(prefs, app_id, app_info)); - std::unique_ptr<App> app = AppPublisher::MakeApp( + auto app = AppPublisher::MakeApp( AppType::kArc, app_id, app_info.suspended ? Readiness::kDisabledByPolicy : Readiness::kReady, app_info.name, install_reason, @@ -1688,9 +1687,6 @@ void ArcApps::ConvertAndPublishPackageApps( const arc::mojom::ArcPackageInfo& package_info, bool update_icon) { - if (!package_info.permissions.has_value()) { - return; - } ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_); if (prefs) { for (const auto& app_id : @@ -1737,7 +1733,7 @@ icon_key_factory_.MakeIconKey(GetIconEffects(app_id, *app_info)); PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = std::make_unique<App>(AppType::kArc, app_id); + auto app = std::make_unique<App>(AppType::kArc, app_id); app->icon_key = std::move( *icon_key_factory_.CreateIconKey(GetIconEffects(app_id, *app_info))); AppPublisher::Publish(std::move(app));
diff --git a/chrome/browser/apps/app_service/publishers/arc_apps.h b/chrome/browser/apps/app_service/publishers/arc_apps.h index afbe711f..90537c5e 100644 --- a/chrome/browser/apps/app_service/publishers/arc_apps.h +++ b/chrome/browser/apps/app_service/publishers/arc_apps.h
@@ -203,10 +203,10 @@ IconEffects icon_effects, apps::LoadIconCallback callback); - std::unique_ptr<App> CreateApp(ArcAppListPrefs* prefs, - const std::string& app_id, - const ArcAppListPrefs::AppInfo& app_info, - bool update_icon = true); + AppPtr CreateApp(ArcAppListPrefs* prefs, + const std::string& app_id, + const ArcAppListPrefs::AppInfo& app_info, + bool update_icon = true); apps::mojom::AppPtr Convert(ArcAppListPrefs* prefs, const std::string& app_id, const ArcAppListPrefs::AppInfo& app_info,
diff --git a/chrome/browser/apps/app_service/publishers/borealis_apps.cc b/chrome/browser/apps/app_service/publishers/borealis_apps.cc index 181957f..c380711 100644 --- a/chrome/browser/apps/app_service/publishers/borealis_apps.cc +++ b/chrome/browser/apps/app_service/publishers/borealis_apps.cc
@@ -81,9 +81,8 @@ app.handles_intents = allowed; } -std::unique_ptr<apps::App> CreateBorealisLauncher(Profile* profile, - bool allowed) { - std::unique_ptr<apps::App> app = apps::AppPublisher::MakeApp( +apps::AppPtr CreateBorealisLauncher(Profile* profile, bool allowed) { + auto app = apps::AppPublisher::MakeApp( apps::AppType::kBorealis, borealis::kInstallerAppId, allowed ? apps::Readiness::kReady : apps::Readiness::kDisabledByPolicy, l10n_util::GetStringUTF8(IDS_BOREALIS_APP_NAME), @@ -188,7 +187,7 @@ return registry; } -std::unique_ptr<App> BorealisApps::CreateApp( +AppPtr BorealisApps::CreateApp( const guest_os::GuestOsRegistryService::Registration& registration, bool generate_new_icon_key) { // We must only convert borealis apps. @@ -199,7 +198,7 @@ // it can't be converted. DCHECK_NE(registration.app_id(), borealis::kInstallerAppId); - std::unique_ptr<App> app = AppPublisher::MakeApp( + auto app = AppPublisher::MakeApp( AppType::kBorealis, registration.app_id(), Readiness::kReady, registration.Name(), InstallReason::kUser, InstallSource::kUnknown); @@ -277,7 +276,7 @@ RegisterPublisher(AppType::kBorealis); - std::vector<std::unique_ptr<App>> apps; + std::vector<AppPtr> apps; apps.push_back( CreateBorealisLauncher(profile_, IsBorealisLauncherAllowed(profile_))); @@ -427,8 +426,7 @@ mojom_app->readiness = apps::mojom::Readiness::kUninstalledByUser; PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = - std::make_unique<App>(AppType::kBorealis, app_id); + auto app = std::make_unique<App>(AppType::kBorealis, app_id); app->readiness = Readiness::kUninstalledByUser; AppPublisher::Publish(std::move(app)); @@ -458,8 +456,7 @@ mojom_app->readiness = apps::mojom::Readiness::kUninstalledByUser; PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = - std::make_unique<App>(AppType::kBorealis, app_id); + auto app = std::make_unique<App>(AppType::kBorealis, app_id); app->readiness = Readiness::kUninstalledByUser; AppPublisher::Publish(std::move(app)); } @@ -484,7 +481,7 @@ PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = AppPublisher::MakeApp( + auto app = AppPublisher::MakeApp( AppType::kBorealis, shelf_app_id, Readiness::kReady, shelf_app_name, InstallReason::kUser, InstallSource::kUnknown); @@ -511,8 +508,7 @@ } for (auto readiness : {Readiness::kUninstalledByUser, Readiness::kRemoved}) { - std::unique_ptr<App> app = - std::make_unique<App>(AppType::kBorealis, shelf_app_id); + auto app = std::make_unique<App>(AppType::kBorealis, shelf_app_id); app->readiness = readiness; AppPublisher::Publish(std::move(app)); }
diff --git a/chrome/browser/apps/app_service/publishers/borealis_apps.h b/chrome/browser/apps/app_service/publishers/borealis_apps.h index 55e47a99..bde446f 100644 --- a/chrome/browser/apps/app_service/publishers/borealis_apps.h +++ b/chrome/browser/apps/app_service/publishers/borealis_apps.h
@@ -57,7 +57,7 @@ guest_os::GuestOsRegistryService* Registry(); // Turns GuestOsRegistry's "app" into one the AppService can use. - std::unique_ptr<App> CreateApp( + AppPtr CreateApp( const guest_os::GuestOsRegistryService::Registration& registration, bool generate_new_icon_key);
diff --git a/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc b/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc index 33b6c989..4a842ea 100644 --- a/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc +++ b/chrome/browser/apps/app_service/publishers/built_in_chromeos_apps.cc
@@ -27,15 +27,14 @@ namespace { -std::unique_ptr<apps::App> CreateApp( - const app_list::InternalApp& internal_app) { +apps::AppPtr CreateApp(const app_list::InternalApp& internal_app) { if ((internal_app.app_id == nullptr) || (internal_app.name_string_resource_id == 0) || (internal_app.icon_resource_id <= 0)) { return nullptr; } - std::unique_ptr<apps::App> app = apps::AppPublisher::MakeApp( + auto app = apps::AppPublisher::MakeApp( apps::AppType::kBuiltIn, internal_app.app_id, apps::Readiness::kReady, l10n_util::GetStringUTF8(internal_app.name_string_resource_id), apps::InstallReason::kSystem, apps::InstallSource::kSystem); @@ -118,9 +117,9 @@ RegisterPublisher(AppType::kBuiltIn); - std::vector<std::unique_ptr<App>> apps; + std::vector<AppPtr> apps; for (const auto& internal_app : app_list::GetInternalAppList(profile_)) { - std::unique_ptr<App> app = CreateApp(internal_app); + AppPtr app = CreateApp(internal_app); if (app) { apps.push_back(std::move(app)); }
diff --git a/chrome/browser/apps/app_service/publishers/crostini_apps.cc b/chrome/browser/apps/app_service/publishers/crostini_apps.cc index af2bf4ac..350440ea3 100644 --- a/chrome/browser/apps/app_service/publishers/crostini_apps.cc +++ b/chrome/browser/apps/app_service/publishers/crostini_apps.cc
@@ -99,7 +99,7 @@ RegisterPublisher(AppType::kCrostini); - std::vector<std::unique_ptr<App>> apps; + std::vector<AppPtr> apps; for (const auto& pair : registry_->GetRegisteredApps(guest_os::GuestOsRegistryService::VmType:: ApplicationList_VmType_TERMINA)) { @@ -306,8 +306,7 @@ mojom_app->readiness = apps::mojom::Readiness::kUninstalledByUser; PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = - std::make_unique<App>(AppType::kCrostini, app_id); + auto app = std::make_unique<App>(AppType::kCrostini, app_id); app->readiness = Readiness::kUninstalledByUser; AppPublisher::Publish(std::move(app)); } @@ -341,8 +340,8 @@ mojom_app->handles_intents = show; PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = std::make_unique<App>( - AppType::kCrostini, crostini::kCrostiniTerminalSystemAppId); + auto app = std::make_unique<App>(AppType::kCrostini, + crostini::kCrostiniTerminalSystemAppId); app->show_in_launcher = crostini_enabled_; app->show_in_shelf = crostini_enabled_; app->show_in_search = true; @@ -351,14 +350,14 @@ } } -std::unique_ptr<App> CrostiniApps::CreateApp( +AppPtr CrostiniApps::CreateApp( const guest_os::GuestOsRegistryService::Registration& registration, bool generate_new_icon_key) { DCHECK_EQ( registration.VmType(), guest_os::GuestOsRegistryService::VmType::ApplicationList_VmType_TERMINA); - std::unique_ptr<App> app = AppPublisher::MakeApp( + auto app = AppPublisher::MakeApp( AppType::kCrostini, registration.app_id(), Readiness::kReady, registration.Name(), InstallReason::kUser, InstallSource::kUnknown);
diff --git a/chrome/browser/apps/app_service/publishers/crostini_apps.h b/chrome/browser/apps/app_service/publishers/crostini_apps.h index e6d1d53..0451f6a 100644 --- a/chrome/browser/apps/app_service/publishers/crostini_apps.h +++ b/chrome/browser/apps/app_service/publishers/crostini_apps.h
@@ -110,7 +110,7 @@ // once it can support hiding apps. void OnCrostiniEnabledChanged(); - std::unique_ptr<App> CreateApp( + AppPtr CreateApp( const guest_os::GuestOsRegistryService::Registration& registration, bool generate_new_icon_key);
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps.cc b/chrome/browser/apps/app_service/publishers/extension_apps.cc index 0ead203..8c2b806a 100644 --- a/chrome/browser/apps/app_service/publishers/extension_apps.cc +++ b/chrome/browser/apps/app_service/publishers/extension_apps.cc
@@ -40,10 +40,9 @@ return true; } -std::unique_ptr<App> ExtensionApps::CreateApp( - const extensions::Extension* extension, - Readiness readiness) { - std::unique_ptr<App> app = CreateAppImpl(extension, readiness); +AppPtr ExtensionApps::CreateApp(const extensions::Extension* extension, + Readiness readiness) { + auto app = CreateAppImpl(extension, readiness); app->icon_key = std::move(*icon_key_factory().CreateIconKey(GetIconEffects(extension))); app->has_badge = false;
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps.h b/chrome/browser/apps/app_service/publishers/extension_apps.h index 2766d04..e371885 100644 --- a/chrome/browser/apps/app_service/publishers/extension_apps.h +++ b/chrome/browser/apps/app_service/publishers/extension_apps.h
@@ -49,8 +49,8 @@ // ExtensionAppsBase overrides. bool Accepts(const extensions::Extension* extension) override; bool ShouldShownInLauncher(const extensions::Extension* extension) override; - std::unique_ptr<App> CreateApp(const extensions::Extension* extension, - Readiness readiness) override; + AppPtr CreateApp(const extensions::Extension* extension, + Readiness readiness) override; apps::mojom::AppPtr Convert(const extensions::Extension* extension, apps::mojom::Readiness readiness) override; };
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps_base.cc b/chrome/browser/apps/app_service/publishers/extension_apps_base.cc index a0b077f..fb15aad9 100644 --- a/chrome/browser/apps/app_service/publishers/extension_apps_base.cc +++ b/chrome/browser/apps/app_service/publishers/extension_apps_base.cc
@@ -178,7 +178,7 @@ SetShowInFields(mojom_app, extension); PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = std::make_unique<App>(app_type(), extension->id()); + auto app = std::make_unique<App>(app_type(), extension->id()); app->readiness = reason == extensions::UNINSTALL_REASON_MIGRATED ? Readiness::kUninstalledByMigration : Readiness::kUninstalledByUser; @@ -217,16 +217,15 @@ } } -std::unique_ptr<App> ExtensionAppsBase::CreateAppImpl( - const extensions::Extension* extension, - Readiness readiness) { +AppPtr ExtensionAppsBase::CreateAppImpl(const extensions::Extension* extension, + Readiness readiness) { auto install_reason = ConvertMojomInstallReasonToInstallReason( GetInstallReason(profile_, extension)); - std::unique_ptr<App> app = AppPublisher::MakeApp( - app_type(), extension->id(), readiness, extension->name(), install_reason, - install_reason == InstallReason::kSystem - ? InstallSource::kSystem - : InstallSource::kChromeWebStore); + auto app = AppPublisher::MakeApp(app_type(), extension->id(), readiness, + extension->name(), install_reason, + install_reason == InstallReason::kSystem + ? InstallSource::kSystem + : InstallSource::kChromeWebStore); app->short_name = extension->short_name(); app->description = extension->description(); app->version = extension->GetVersionForDisplay(); @@ -395,7 +394,7 @@ } void ExtensionAppsBase::OnExtensionsReady() { - std::vector<std::unique_ptr<App>> apps; + std::vector<AppPtr> apps; extensions::ExtensionRegistry* registry = extensions::ExtensionRegistry::Get(profile_); CreateAppVector(registry->enabled_extensions(), Readiness::kReady, &apps); @@ -741,7 +740,7 @@ mojom_app->readiness = mojom_readiness; PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = std::make_unique<App>(app_type(), extension->id()); + auto app = std::make_unique<App>(app_type(), extension->id()); app->readiness = readiness; AppPublisher::Publish(std::move(app)); } @@ -820,7 +819,7 @@ void ExtensionAppsBase::CreateAppVector( const extensions::ExtensionSet& extensions, Readiness readiness, - std::vector<std::unique_ptr<App>>* apps_out) { + std::vector<AppPtr>* apps_out) { for (const auto& extension : extensions) { if (Accepts(extension.get())) { apps_out->push_back(CreateApp(extension.get(), readiness));
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps_base.h b/chrome/browser/apps/app_service/publishers/extension_apps_base.h index d676ff1..e8b2c83 100644 --- a/chrome/browser/apps/app_service/publishers/extension_apps_base.h +++ b/chrome/browser/apps/app_service/publishers/extension_apps_base.h
@@ -8,6 +8,7 @@ #include <map> #include <memory> #include <string> +#include <vector> #include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" @@ -81,8 +82,8 @@ virtual void SetShowInFields(apps::mojom::AppPtr& app, const extensions::Extension* extension); - std::unique_ptr<App> CreateAppImpl(const extensions::Extension* extension, - Readiness readiness); + AppPtr CreateAppImpl(const extensions::Extension* extension, + Readiness readiness); apps::mojom::AppPtr ConvertImpl(const extensions::Extension* extension, apps::mojom::Readiness readiness); @@ -226,15 +227,15 @@ void PopulateIntentFilters(const absl::optional<GURL>& app_scope, std::vector<mojom::IntentFilterPtr>* target); - virtual std::unique_ptr<App> CreateApp(const extensions::Extension* extension, - Readiness readiness) = 0; + virtual AppPtr CreateApp(const extensions::Extension* extension, + Readiness readiness) = 0; virtual apps::mojom::AppPtr Convert(const extensions::Extension* extension, apps::mojom::Readiness readiness) = 0; void CreateAppVector(const extensions::ExtensionSet& extensions, Readiness readiness, - std::vector<std::unique_ptr<App>>* apps_out); + std::vector<AppPtr>* apps_out); void ConvertVector(const extensions::ExtensionSet& extensions, apps::mojom::Readiness readiness,
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc index 65d94b1..2d298bf 100644 --- a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc +++ b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.cc
@@ -666,7 +666,7 @@ SetShowInFields(mojom_app, extension); PublisherBase::Publish(std::move(mojom_app), subscribers()); - std::unique_ptr<App> app = std::make_unique<App>(app_type(), app_id); + auto app = std::make_unique<App>(app_type(), app_id); SetShowInFields(extension, *app); AppPublisher::Publish(std::move(app)); } @@ -794,9 +794,8 @@ return app_list::ShouldShowInLauncher(extension, profile()); } -std::unique_ptr<App> ExtensionAppsChromeOs::CreateApp( - const extensions::Extension* extension, - Readiness readiness) { +AppPtr ExtensionAppsChromeOs::CreateApp(const extensions::Extension* extension, + Readiness readiness) { // If Lacros is publishing chrome apps, then by default ash chrome apps should // be disabled. There is a keep-list that serves as the exception. const bool disable_for_lacros = @@ -806,7 +805,7 @@ const bool is_app_disabled = base::Contains(disabled_apps_, extension->id()) || disable_for_lacros; - std::unique_ptr<App> app = CreateAppImpl( + auto app = CreateAppImpl( extension, is_app_disabled ? Readiness::kDisabledByPolicy : readiness); bool paused = paused_apps_.IsPaused(extension->id()); app->icon_key = std::move( @@ -931,7 +930,7 @@ GetIconEffects(extension, paused_apps_.IsPaused(app_id))); PublisherBase::Publish(std::move(mojom_app), subscribers()); - std::unique_ptr<App> app = std::make_unique<App>(app_type(), app_id); + auto app = std::make_unique<App>(app_type(), app_id); app->icon_key = std::move(*icon_key_factory().CreateIconKey( GetIconEffects(extension, paused_apps_.IsPaused(app_id)))); AppPublisher::Publish(std::move(app));
diff --git a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.h b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.h index 5725978..089e5b2c 100644 --- a/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.h +++ b/chrome/browser/apps/app_service/publishers/extension_apps_chromeos.h
@@ -147,8 +147,8 @@ void SetShowInFields(apps::mojom::AppPtr& app, const extensions::Extension* extension) override; bool ShouldShownInLauncher(const extensions::Extension* extension) override; - std::unique_ptr<App> CreateApp(const extensions::Extension* extension, - Readiness readiness) override; + AppPtr CreateApp(const extensions::Extension* extension, + Readiness readiness) override; apps::mojom::AppPtr Convert(const extensions::Extension* extension, apps::mojom::Readiness readiness) override;
diff --git a/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc b/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc index d1317618..6beab0f6 100644 --- a/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc +++ b/chrome/browser/apps/app_service/publishers/plugin_vm_apps.cc
@@ -114,8 +114,8 @@ return permissions; } -std::unique_ptr<apps::App> CreatePluginVmApp(Profile* profile, bool allowed) { - std::unique_ptr<apps::App> app = apps::AppPublisher::MakeApp( +apps::AppPtr CreatePluginVmApp(Profile* profile, bool allowed) { + auto app = apps::AppPublisher::MakeApp( apps::AppType::kPluginVm, plugin_vm::kPluginVmShelfAppId, allowed ? apps::Readiness::kReady : apps::Readiness::kDisabledByPolicy, l10n_util::GetStringUTF8(IDS_PLUGIN_VM_APP_NAME), @@ -236,7 +236,7 @@ RegisterPublisher(AppType::kPluginVm); - std::vector<std::unique_ptr<App>> apps; + std::vector<AppPtr> apps; apps.push_back(CreatePluginVmApp(profile_, is_allowed_)); for (const auto& pair : registry_->GetRegisteredApps(guest_os::GuestOsRegistryService::VmType:: @@ -373,8 +373,7 @@ mojom_app->readiness = apps::mojom::Readiness::kUninstalledByUser; PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = - std::make_unique<App>(AppType::kPluginVm, app_id); + auto app = std::make_unique<App>(AppType::kPluginVm, app_id); app->readiness = apps::Readiness::kUninstalledByUser; AppPublisher::Publish(std::move(app)); } @@ -388,13 +387,13 @@ } } -std::unique_ptr<App> PluginVmApps::CreateApp( +AppPtr PluginVmApps::CreateApp( const guest_os::GuestOsRegistryService::Registration& registration, bool generate_new_icon_key) { DCHECK_EQ(registration.VmType(), guest_os::GuestOsRegistryService::VmType:: ApplicationList_VmType_PLUGIN_VM); - std::unique_ptr<App> app = AppPublisher::MakeApp( + auto app = AppPublisher::MakeApp( AppType::kPluginVm, registration.app_id(), Readiness::kReady, registration.Name(), InstallReason::kUser, apps::InstallSource::kUnknown); @@ -455,7 +454,7 @@ SetAppAllowed(mojom_app.get(), is_allowed); PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = + auto app = std::make_unique<App>(AppType::kPluginVm, plugin_vm::kPluginVmShelfAppId); SetAppAllowed(is_allowed, *app); AppPublisher::Publish(std::move(app)); @@ -471,7 +470,7 @@ plugin_vm::PluginVmFeatures::Get()->IsConfigured(profile_)); PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = + auto app = std::make_unique<App>(AppType::kPluginVm, plugin_vm::kPluginVmShelfAppId); app->show_in_management = plugin_vm::PluginVmFeatures::Get()->IsConfigured(profile_); @@ -485,7 +484,7 @@ PopulatePermissions(mojom_app.get(), profile_); PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = + auto app = std::make_unique<App>(AppType::kPluginVm, plugin_vm::kPluginVmShelfAppId); app->permissions = CreatePermissions(profile_); AppPublisher::Publish(std::move(app));
diff --git a/chrome/browser/apps/app_service/publishers/plugin_vm_apps.h b/chrome/browser/apps/app_service/publishers/plugin_vm_apps.h index 895d3bd..9133dad 100644 --- a/chrome/browser/apps/app_service/publishers/plugin_vm_apps.h +++ b/chrome/browser/apps/app_service/publishers/plugin_vm_apps.h
@@ -94,7 +94,7 @@ const std::vector<std::string>& removed_apps, const std::vector<std::string>& inserted_apps) override; - std::unique_ptr<App> CreateApp( + AppPtr CreateApp( const guest_os::GuestOsRegistryService::Registration& registration, bool generate_new_icon_key);
diff --git a/chrome/browser/apps/app_service/publishers/remote_apps.cc b/chrome/browser/apps/app_service/publishers/remote_apps.cc index ae1331a3..3c168bd 100644 --- a/chrome/browser/apps/app_service/publishers/remote_apps.cc +++ b/chrome/browser/apps/app_service/publishers/remote_apps.cc
@@ -61,11 +61,10 @@ AppPublisher::Publish(std::move(app)); } -std::unique_ptr<App> RemoteApps::CreateApp( - const ash::RemoteAppsModel::AppInfo& info) { - std::unique_ptr<App> app = AppPublisher::MakeApp( - AppType::kRemote, info.id, Readiness::kReady, info.name, - InstallReason::kUser, apps::InstallSource::kUnknown); +AppPtr RemoteApps::CreateApp(const ash::RemoteAppsModel::AppInfo& info) { + auto app = AppPublisher::MakeApp(AppType::kRemote, info.id, Readiness::kReady, + info.name, InstallReason::kUser, + apps::InstallSource::kUnknown); app->icon_key = std::move(*icon_key_factory_.CreateIconKey(IconEffects::kNone)); app->show_in_launcher = true;
diff --git a/chrome/browser/apps/app_service/publishers/remote_apps.h b/chrome/browser/apps/app_service/publishers/remote_apps.h index 34b3826..ac6a73b 100644 --- a/chrome/browser/apps/app_service/publishers/remote_apps.h +++ b/chrome/browser/apps/app_service/publishers/remote_apps.h
@@ -75,7 +75,7 @@ private: friend class ash::RemoteAppsManager; - std::unique_ptr<App> CreateApp(const ash::RemoteAppsModel::AppInfo& info); + AppPtr CreateApp(const ash::RemoteAppsModel::AppInfo& info); apps::mojom::AppPtr Convert(const ash::RemoteAppsModel::AppInfo& info);
diff --git a/chrome/browser/apps/app_service/publishers/standalone_browser_apps.cc b/chrome/browser/apps/app_service/publishers/standalone_browser_apps.cc index 8e9e22c..8d10619 100644 --- a/chrome/browser/apps/app_service/publishers/standalone_browser_apps.cc +++ b/chrome/browser/apps/app_service/publishers/standalone_browser_apps.cc
@@ -41,7 +41,7 @@ resource_id = IDR_PRODUCT_LOGO_256_CANARY; #endif - std::unique_ptr<apps::IconKey> icon_key = std::make_unique<apps::IconKey>( + auto icon_key = std::make_unique<apps::IconKey>( apps::IconKey::kDoesNotChangeOverTime, resource_id, icon_effects); return icon_key; } @@ -59,8 +59,8 @@ StandaloneBrowserApps::~StandaloneBrowserApps() = default; -std::unique_ptr<App> StandaloneBrowserApps::CreateStandaloneBrowserApp() { - std::unique_ptr<App> app = AppPublisher::MakeApp( +AppPtr StandaloneBrowserApps::CreateStandaloneBrowserApp() { + auto app = AppPublisher::MakeApp( AppType::kStandaloneBrowser, app_constants::kLacrosAppId, Readiness::kReady, "Lacros" /* TODO(crbug.com/1267752): Localized name.*/, InstallReason::kSystem, InstallSource::kSystem); @@ -232,8 +232,8 @@ mojom_app->icon_key = NewIconKey(); PublisherBase::Publish(std::move(mojom_app), subscribers_); - std::unique_ptr<App> app = std::make_unique<App>(AppType::kStandaloneBrowser, - app_constants::kLacrosAppId); + auto app = std::make_unique<App>(AppType::kStandaloneBrowser, + app_constants::kLacrosAppId); app->icon_key = std::move(*CreateIconKey(success)); AppPublisher::Publish(std::move(app)); }
diff --git a/chrome/browser/apps/app_service/publishers/standalone_browser_apps.h b/chrome/browser/apps/app_service/publishers/standalone_browser_apps.h index ef5534f..e1329099 100644 --- a/chrome/browser/apps/app_service/publishers/standalone_browser_apps.h +++ b/chrome/browser/apps/app_service/publishers/standalone_browser_apps.h
@@ -50,7 +50,7 @@ friend class PublisherHost; // Returns the single lacros app. - std::unique_ptr<App> CreateStandaloneBrowserApp(); + AppPtr CreateStandaloneBrowserApp(); // Returns the single lacros app. apps::mojom::AppPtr GetStandaloneBrowserApp();
diff --git a/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc b/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc index 0f9aaa7a..80943b2 100644 --- a/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc +++ b/chrome/browser/apps/app_service/publishers/standalone_browser_extension_apps.cc
@@ -252,7 +252,7 @@ return; } - std::vector<std::unique_ptr<App>> apps; + std::vector<AppPtr> apps; for (apps::mojom::AppPtr& delta : deltas) { apps.push_back(ConvertMojomAppToApp(delta)); app_ptr_cache_[delta->app_id] = delta.Clone();
diff --git a/chrome/browser/apps/app_service/publishers/web_apps_crosapi.cc b/chrome/browser/apps/app_service/publishers/web_apps_crosapi.cc index db54176..1d265845 100644 --- a/chrome/browser/apps/app_service/publishers/web_apps_crosapi.cc +++ b/chrome/browser/apps/app_service/publishers/web_apps_crosapi.cc
@@ -21,7 +21,6 @@ #include "chrome/browser/apps/app_service/launch_utils.h" #include "chrome/browser/apps/app_service/menu_util.h" #include "chrome/browser/web_applications/web_app_utils.h" -#include "chrome/common/chrome_features.h" #include "chrome/grit/generated_resources.h" #include "components/services/app_service/public/cpp/crosapi_utils.h" #include "components/services/app_service/public/cpp/instance_registry.h" @@ -253,20 +252,16 @@ apps::AddCommandItem(ash::SHOW_APP_INFO, IDS_APP_CONTEXT_MENU_SHOW_INFO, &menu_items); } - if (base::FeatureList::IsEnabled( - features::kDesktopPWAsAppIconShortcutsMenuUI)) { - if (!LogIfNotConnected(FROM_HERE)) { - std::move(callback).Run(std::move(menu_items)); - return; - } - controller_->GetMenuModel( - app_id, base::BindOnce(&WebAppsCrosapi::OnGetMenuModelFromCrosapi, - weak_factory_.GetWeakPtr(), app_id, menu_type, - std::move(menu_items), std::move(callback))); - } else { + if (!LogIfNotConnected(FROM_HERE)) { std::move(callback).Run(std::move(menu_items)); + return; } + + controller_->GetMenuModel( + app_id, base::BindOnce(&WebAppsCrosapi::OnGetMenuModelFromCrosapi, + weak_factory_.GetWeakPtr(), app_id, menu_type, + std::move(menu_items), std::move(callback))); } void WebAppsCrosapi::OnGetMenuModelFromCrosapi( @@ -369,7 +364,7 @@ if (!web_app::IsWebAppsCrosapiEnabled()) return; - std::vector<std::unique_ptr<App>> apps; + std::vector<AppPtr> apps; for (apps::mojom::AppPtr& delta : deltas) { apps.push_back(ConvertMojomAppToApp(delta)); }
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc index 415cdde6..efd9547 100644 --- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc +++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac.cc
@@ -19,7 +19,6 @@ #include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/browser/web_applications/web_app_shortcut_mac.h" #include "chrome/browser/web_applications/web_app_utils.h" -#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "net/base/filename_util.h" #include "third_party/blink/public/common/custom_handlers/protocol_handler_utils.h" @@ -352,11 +351,6 @@ std::vector<chrome::mojom::ApplicationDockMenuItemPtr> dock_menu_items; - if (!base::FeatureList::IsEnabled( - features::kDesktopPWAsAppIconShortcutsMenuUI)) { - return dock_menu_items; - } - DCHECK(profile); auto shortcuts_menu_item_infos = WebAppProvider::GetForWebApps(profile)
diff --git a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc index fbad0863..67bdd37 100644 --- a/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc +++ b/chrome/browser/apps/app_shim/web_app_shim_manager_delegate_mac_unittest.cc
@@ -8,7 +8,6 @@ #include "base/command_line.h" #include "base/files/file_path.h" #include "base/test/bind.h" -#include "base/test/scoped_feature_list.h" #include "chrome/browser/apps/app_service/app_launch_params.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/web_applications/test/fake_web_app_provider.h" @@ -16,7 +15,6 @@ #include "chrome/browser/web_applications/test/web_app_test.h" #include "chrome/browser/web_applications/web_app.h" #include "chrome/browser/web_applications/web_app_provider.h" -#include "chrome/common/chrome_features.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -381,34 +379,16 @@ std::unique_ptr<MockDelegate> delegate = std::make_unique<MockDelegate>(); WebAppShimManagerDelegate shim_manager(std::move(delegate)); - // Validate empty array when feature flag is off. + // Validate empty array when app does not have shortcut menus declared in the + // manifest. { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndDisableFeature( - features::kDesktopPWAsAppIconShortcutsMenuUI); auto shortcut_menu_items = shim_manager.GetAppShortcutsMenuItemInfos(profile(), AppId()); EXPECT_EQ(0U, shortcut_menu_items.size()); } - // Validate empty array when feature flag is on, and app does not have - // shortcut menus declared in the manifest. + // Validate array when app does declare shortcut menus in the manifest. { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature( - features::kDesktopPWAsAppIconShortcutsMenuUI); - auto shortcut_menu_items = - shim_manager.GetAppShortcutsMenuItemInfos(profile(), AppId()); - EXPECT_EQ(0U, shortcut_menu_items.size()); - } - - // Validate array when feature flag is on, and app does declare shortcut menus - // in the manifest. - { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature( - features::kDesktopPWAsAppIconShortcutsMenuUI); - // Install a dummy app with shortcut menu items auto web_app_info = std::make_unique<WebAppInstallInfo>(); WebAppShortcutsMenuItemInfo shortcut_info1;
diff --git a/chrome/browser/ash/accessibility/dictation_browsertest.cc b/chrome/browser/ash/accessibility/dictation_browsertest.cc index 4ef9c53d..42396d9 100644 --- a/chrome/browser/ash/accessibility/dictation_browsertest.cc +++ b/chrome/browser/ash/accessibility/dictation_browsertest.cc
@@ -1024,7 +1024,22 @@ waiter.Wait(); } + void WaitForHelpUrlVisible() { + SuccessWaiter waiter( + base::BindRepeating(&DictationCommandsExtensionTest::IsHelpUrlVisible, + base::Unretained(this))); + waiter.Wait(); + base::RunLoop().RunUntilIdle(); + } + private: + bool IsHelpUrlVisible() { + content::WebContents* web_contents = + browser()->tab_strip_model()->GetActiveWebContents(); + return web_contents->GetVisibleURL().spec().rfind( + "https://support.google.com/chromebook", /*pos=*/0) != 0; + } + base::test::ScopedFeatureList scoped_feature_list_; }; @@ -1163,6 +1178,13 @@ /*expected_bucket_count=*/1); } +IN_PROC_BROWSER_TEST_P(DictationCommandsExtensionTest, Help) { + SendFinalFakeSpeechResultAndWait("help"); + WaitForHelpUrlVisible(); + // Opening a new tab with the help center article toggles Dictation off. + WaitForRecognitionStopped(); +} + // Tests the behavior of the Dictation bubble UI. class DictationUITest : public DictationCommandsExtensionTest { protected: @@ -1297,23 +1319,6 @@ u"Try saying:", u"\"Type [word / phrase]\"", u"\"Help\""}); } -// TODO(1266696): DictationCommandsExtensionTest.Help is failing on -// linux-chromeos-debug. -#if BUILDFLAG(IS_CHROMEOS) -#define MAYBE_Help DISABLED_Help -#else -#define MAYBE_Help Help -#endif -IN_PROC_BROWSER_TEST_P(DictationCommandsExtensionTest, MAYBE_Help) { - SendFinalFakeSpeechResultAndWait("HELP"); - // Opening a new tab with the help center article toggles Dictation off. - WaitForRecognitionStopped(); - content::WebContents* web_contents = - browser()->tab_strip_model()->GetActiveWebContents(); - EXPECT_TRUE(web_contents->GetVisibleURL().spec().rfind( - "https://support.google.com/chromebook", /*pos=*/0) != 0); -} - // TODO(crbug.com/1264544): Test looking at gn args has pumpkin and does // repeats.
diff --git a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc index 29600f1..24c6ecff 100644 --- a/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc +++ b/chrome/browser/ash/app_mode/arc/arc_kiosk_app_service_unittest.cc
@@ -141,7 +141,6 @@ package->last_backup_time = 1; package->sync = false; package->system = false; - package->permissions = base::flat_map<::arc::mojom::AppPermission, bool>(); return package; }
diff --git a/chrome/browser/ash/app_restore/arc_app_launch_handler.cc b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc index 33cedf4..1ea72f5 100644 --- a/chrome/browser/ash/app_restore/arc_app_launch_handler.cc +++ b/chrome/browser/ash/app_restore/arc_app_launch_handler.cc
@@ -25,6 +25,7 @@ #include "chrome/browser/ash/app_restore/arc_window_utils.h" #include "chrome/browser/ash/app_restore/full_restore_app_launch_handler.h" #include "chrome/browser/ash/arc/arc_util.h" +#include "chrome/browser/ash/arc/window_predictor/window_predictor_utils.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_process_platform_part.h" #include "chrome/browser/profiles/profile.h" @@ -428,8 +429,7 @@ bool launch_ghost_window = false; #if BUILDFLAG(ENABLE_WAYLAND_SERVER) if (window_handler_ && - (data_it.second->bounds_in_root.has_value() || - data_it.second->current_bounds.has_value()) && + arc::CanLaunchGhostWindowByRestoreData(*data_it.second) && window_handler_->LaunchArcGhostWindow(app_id, arc_session_id, data_it.second.get())) { launch_ghost_window = true;
diff --git a/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc index 8e94c48e..1ec1ad8 100644 --- a/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc +++ b/chrome/browser/ash/app_restore/arc_ghost_window_shell_surface.cc
@@ -15,10 +15,25 @@ #include "components/exo/buffer.h" #include "gpu/command_buffer/client/gpu_memory_buffer_manager.h" #include "ui/aura/env.h" +#include "ui/display/screen.h" #include "ui/views/window/caption_button_types.h" namespace { constexpr int kDiameter = 24; + +bool IsMaximizedState( + const absl::optional<chromeos::WindowStateType>& window_state) { + return window_state.has_value() && + (window_state.value() == chromeos::WindowStateType::kMaximized || + window_state.value() == chromeos::WindowStateType::kFullscreen); +} + +bool IsMinimizedState( + const absl::optional<chromeos::WindowStateType>& window_state) { + return window_state.has_value() && + window_state.value() == chromeos::WindowStateType::kMinimized; +} + } // namespace namespace ash { @@ -64,12 +79,27 @@ const gfx::Rect& bounds, app_restore::AppRestoreData* restore_data, base::RepeatingClosure close_callback) { + // ArcGhostWindowShellSurface need a valid display id, or it cannot be + // created. int64_t display_id_value = restore_data->display_id.value_or(display::kInvalidDisplayId); absl::optional<double> scale_factor = GetDisplayScaleFactor(display_id_value); if (!scale_factor.has_value()) return nullptr; + const auto& window_state = restore_data->window_state_type; + gfx::Rect local_bounds = bounds; + // If the window is maximize / minimized, the initial bounds will be + // unnecessary. Here set it as display size to ensure the content render is + // correct. + if (local_bounds.IsEmpty()) { + DCHECK(IsMaximizedState(window_state) || IsMinimizedState(window_state)); + display::Display disp; + display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id_value, + &disp); + local_bounds = disp.work_area(); + } + // TODO(sstan): Fallback to system default color or other topic color, if // the task hasn't valid theme color. uint32_t theme_color = @@ -90,11 +120,11 @@ // TODO(sstan): Add set_surface_destroyed_callback. shell_surface->set_delegate(std::make_unique<ArcGhostWindowDelegate>( shell_surface.get(), window_handler, window_id, display_id_value, - bounds)); + local_bounds)); shell_surface->set_close_callback(std::move(close_callback)); shell_surface->SetAppId(app_id); - shell_surface->SetBounds(display_id_value, bounds); + shell_surface->SetBounds(display_id_value, local_bounds); if (restore_data->maximum_size.has_value()) shell_surface->SetMaximumSize(restore_data->maximum_size.value()); @@ -121,20 +151,21 @@ // Relayout overlay. shell_surface->GetWidget()->LayoutRootViewIfNecessary(); - // Change the minimized at the last operation, since we need create the window - // entity first and hide it on ash shelf. - if (restore_data->window_state_type.has_value() && - restore_data->window_state_type.value() == - chromeos::WindowStateType::kMinimized) { + // Change the window state at the last operation, since we need create the + // window entity first. + if (IsMaximizedState(window_state)) { + shell_surface->SetMaximized(); + shell_surface->controller_surface()->Commit(); + } else if (IsMinimizedState(window_state)) { shell_surface->SetMinimized(); shell_surface->controller_surface()->Commit(); + } else { + // Reset the same bounds, to make sure white background can be located in + // correct place. Without this operation, the white background will not + // at the same location with window bounds. + shell_surface->SetBounds(display_id_value, local_bounds); } - // Reset the same bounds, to make sure white background can be located in - // correct place. Without this operation, the white background will not - // at the same location with window bounds. - shell_surface->SetBounds(display_id_value, bounds); - return shell_surface; }
diff --git a/chrome/browser/ash/arc/intent_helper/arc_settings_service_browsertest.cc b/chrome/browser/ash/arc/intent_helper/arc_settings_service_browsertest.cc index 5a594a8..ed3d1ca9 100644 --- a/chrome/browser/ash/arc/intent_helper/arc_settings_service_browsertest.cc +++ b/chrome/browser/ash/arc/intent_helper/arc_settings_service_browsertest.cc
@@ -200,8 +200,8 @@ DCHECK(count < extras.size()) << "The expected proxy broadcast count is smaller than " "the actual count."; - EXPECT_TRUE(base::JSONReader::ReadDeprecated(broadcast.extras) - ->Equals(extras[count])); + EXPECT_EQ(*base::JSONReader::ReadDeprecated(broadcast.extras), + *extras[count]); count++; } }
diff --git a/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc b/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc index 4bd5c69..c4e5f74 100644 --- a/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc +++ b/chrome/browser/ash/arc/policy/arc_policy_bridge_unittest.cc
@@ -298,8 +298,7 @@ base::JSONReader::ReadDeprecated( policy_bridge()->get_arc_policy_compliance_report()); ASSERT_TRUE(saved_compliance_report_value); - EXPECT_TRUE( - compliance_report_value->Equals(saved_compliance_report_value.get())); + EXPECT_EQ(*compliance_report_value, *saved_compliance_report_value); } else { EXPECT_TRUE(policy_bridge()->get_arc_policy_compliance_report().empty()); }
diff --git a/chrome/browser/ash/arc/window_predictor/arc_predictor_app_launch_handler.cc b/chrome/browser/ash/arc/window_predictor/arc_predictor_app_launch_handler.cc index aadf520..9046c7a 100644 --- a/chrome/browser/ash/arc/window_predictor/arc_predictor_app_launch_handler.cc +++ b/chrome/browser/ash/arc/window_predictor/arc_predictor_app_launch_handler.cc
@@ -53,9 +53,17 @@ app_info->arc_session_id = arc_session_id; restore_data()->AddAppLaunchInfo(std::move(app_info)); auto app_window_info = std::make_unique<app_restore::WindowInfo>(); + + // The bounds should be |WindowInfo::ArcExtraInfo::bounds_in_root|, but here + // we always launch the window in corresponding display, so for avoid + // initialize nest struct here we use |current_bounds| (the original sementic + // is bounds in global coordinate) instead. if (window_info->bounds.has_value()) app_window_info->current_bounds = window_info->bounds.value(); + app_window_info->display_id = display_id; + app_window_info->window_state_type = + static_cast<chromeos::WindowStateType>(window_info->state); restore_data()->ModifyWindowInfo(app_id, arc_session_id, *app_window_info); }
diff --git a/chrome/browser/ash/arc/window_predictor/window_predictor_utils.cc b/chrome/browser/ash/arc/window_predictor/window_predictor_utils.cc index 8f79af4..4b3b4b9 100644 --- a/chrome/browser/ash/arc/window_predictor/window_predictor_utils.cc +++ b/chrome/browser/ash/arc/window_predictor/window_predictor_utils.cc
@@ -46,4 +46,13 @@ return true; } +bool CanLaunchGhostWindowByRestoreData( + const app_restore::AppRestoreData& restore_data) { + const bool not_need_bounds = + restore_data.window_state_type == chromeos::WindowStateType::kMaximized || + restore_data.window_state_type == chromeos::WindowStateType::kFullscreen; + return not_need_bounds || restore_data.bounds_in_root.has_value() || + restore_data.current_bounds.has_value(); +} + } // namespace arc
diff --git a/chrome/browser/ash/arc/window_predictor/window_predictor_utils.h b/chrome/browser/ash/arc/window_predictor/window_predictor_utils.h index cc2aa9b..d781934 100644 --- a/chrome/browser/ash/arc/window_predictor/window_predictor_utils.h +++ b/chrome/browser/ash/arc/window_predictor/window_predictor_utils.h
@@ -11,6 +11,10 @@ class Profile; +namespace app_restore { +struct AppRestoreData; +} + namespace arc { // Create ARC app ghost window and add the corresponding to the launching list, @@ -22,6 +26,11 @@ arc::UserInteractionType user_interaction_type, arc::mojom::WindowInfoPtr window_info); +// Is the the window info provide enough data to create corresponding ARC ghost +// window. +bool CanLaunchGhostWindowByRestoreData( + const app_restore::AppRestoreData& restore_data); + } // namespace arc #endif // CHROME_BROWSER_ASH_ARC_WINDOW_PREDICTOR_WINDOW_PREDICTOR_UTILS_H_
diff --git a/chrome/browser/ash/borealis/borealis_context.cc b/chrome/browser/ash/borealis/borealis_context.cc index aed86a2..728c0c7 100644 --- a/chrome/browser/ash/borealis/borealis_context.cc +++ b/chrome/browser/ash/borealis/borealis_context.cc
@@ -107,7 +107,7 @@ void OnDelayComplete(GURL gurl, std::string app_id) { app_delayers_.erase(app_id); - ash::NewWindowDelegate::GetInstance()->OpenUrl( + ash::NewWindowDelegate::GetPrimary()->OpenUrl( gurl, /*from_user_interaction=*/true); }
diff --git a/chrome/browser/ash/browser_context_keyed_service_factories.cc b/chrome/browser/ash/browser_context_keyed_service_factories.cc index f895a7f..abcc964 100644 --- a/chrome/browser/ash/browser_context_keyed_service_factories.cc +++ b/chrome/browser/ash/browser_context_keyed_service_factories.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/ash/authpolicy/authpolicy_credentials_manager.h" #include "chrome/browser/ash/bluetooth/debug_logs_manager_factory.h" #include "chrome/browser/ash/borealis/borealis_service_factory.h" +#include "chrome/browser/ash/bruschetta/bruschetta_service_factory.h" #include "chrome/browser/ash/cert_provisioning/cert_provisioning_scheduler_user_service.h" #include "chrome/browser/ash/crostini/crostini_engagement_metrics_service.h" #include "chrome/browser/ash/eche_app/eche_app_manager_factory.h" @@ -58,6 +59,7 @@ AuthPolicyCredentialsManagerFactory::GetInstance(); bluetooth::DebugLogsManagerFactory::GetInstance(); borealis::BorealisServiceFactory::GetInstance(); + bruschetta::BruschettaServiceFactory::GetInstance(); cert_provisioning::CertProvisioningSchedulerUserServiceFactory::GetInstance(); crostini::CrostiniEngagementMetricsService::Factory::GetInstance(); #if defined(USE_CUPS)
diff --git a/chrome/browser/ash/bruschetta/DIR_METADATA b/chrome/browser/ash/bruschetta/DIR_METADATA new file mode 100644 index 0000000..f461eb4 --- /dev/null +++ b/chrome/browser/ash/bruschetta/DIR_METADATA
@@ -0,0 +1,3 @@ +monorail: { + component: "UI>Shell>Containers" +}
diff --git a/chrome/browser/ash/bruschetta/OWNERS b/chrome/browser/ash/bruschetta/OWNERS new file mode 100644 index 0000000..a33be2b --- /dev/null +++ b/chrome/browser/ash/bruschetta/OWNERS
@@ -0,0 +1 @@ +file://chrome/browser/ash/guest_os/OWNERS
diff --git a/chrome/browser/ash/bruschetta/README.md b/chrome/browser/ash/bruschetta/README.md new file mode 100644 index 0000000..9130fcc --- /dev/null +++ b/chrome/browser/ash/bruschetta/README.md
@@ -0,0 +1,4 @@ +# Bruschetta + +This folder contains code for the Bruschetta (also know as generic or third +party VMs) project). Think Crostini except BYO-VM.
diff --git a/chrome/browser/ash/bruschetta/bruschetta_service.cc b/chrome/browser/ash/bruschetta/bruschetta_service.cc new file mode 100644 index 0000000..ab9dde16 --- /dev/null +++ b/chrome/browser/ash/bruschetta/bruschetta_service.cc
@@ -0,0 +1,13 @@ +// Copyright 2022 The Chromium 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/ash/bruschetta/bruschetta_service.h" + +namespace bruschetta { + +BruschettaService::BruschettaService() = default; + +BruschettaService::~BruschettaService() = default; + +} // namespace bruschetta
diff --git a/chrome/browser/ash/bruschetta/bruschetta_service.h b/chrome/browser/ash/bruschetta/bruschetta_service.h new file mode 100644 index 0000000..b8fb27cc --- /dev/null +++ b/chrome/browser/ash/bruschetta/bruschetta_service.h
@@ -0,0 +1,23 @@ +// Copyright 2022 The Chromium 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_ASH_BRUSCHETTA_BRUSCHETTA_SERVICE_H_ +#define CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_SERVICE_H_ + +#include "components/keyed_service/core/keyed_service.h" + +namespace bruschetta { + +// A service to hold the separate modules that provide Bruschetta +// (third-party/generic VM) support within Chrome (files app integration, app +// service integration, etc). +class BruschettaService : public KeyedService { + public: + BruschettaService(); + ~BruschettaService() override; +}; + +} // namespace bruschetta + +#endif // CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_SERVICE_H_
diff --git a/chrome/browser/ash/bruschetta/bruschetta_service_factory.cc b/chrome/browser/ash/bruschetta/bruschetta_service_factory.cc new file mode 100644 index 0000000..4218db0 --- /dev/null +++ b/chrome/browser/ash/bruschetta/bruschetta_service_factory.cc
@@ -0,0 +1,38 @@ +// Copyright 2022 The Chromium 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/ash/bruschetta/bruschetta_service_factory.h" + +#include "chrome/browser/ash/bruschetta/bruschetta_service.h" +#include "chrome/browser/profiles/profile.h" +#include "components/keyed_service/content/browser_context_dependency_manager.h" + +namespace bruschetta { + +// static +BruschettaService* bruschetta::BruschettaServiceFactory::GetForProfile( + Profile* profile) { + return static_cast<BruschettaService*>( + GetInstance()->GetServiceForBrowserContext(profile, true)); +} + +// static +BruschettaServiceFactory* BruschettaServiceFactory::GetInstance() { + static base::NoDestructor<BruschettaServiceFactory> factory; + return factory.get(); +} + +BruschettaServiceFactory::BruschettaServiceFactory() + : BrowserContextKeyedServiceFactory( + "BruschettaService", + BrowserContextDependencyManager::GetInstance()) {} + +BruschettaServiceFactory::~BruschettaServiceFactory() = default; + +KeyedService* BruschettaServiceFactory::BuildServiceInstanceFor( + content::BrowserContext* context) const { + return new BruschettaService(); +} + +} // namespace bruschetta
diff --git a/chrome/browser/ash/bruschetta/bruschetta_service_factory.h b/chrome/browser/ash/bruschetta/bruschetta_service_factory.h new file mode 100644 index 0000000..52ca0c9 --- /dev/null +++ b/chrome/browser/ash/bruschetta/bruschetta_service_factory.h
@@ -0,0 +1,38 @@ +// Copyright 2022 The Chromium 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_ASH_BRUSCHETTA_BRUSCHETTA_SERVICE_FACTORY_H_ +#define CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_SERVICE_FACTORY_H_ + +#include "base/no_destructor.h" +#include "components/keyed_service/content/browser_context_keyed_service_factory.h" + +class Profile; + +namespace bruschetta { + +class BruschettaService; + +class BruschettaServiceFactory : public BrowserContextKeyedServiceFactory { + public: + static bruschetta::BruschettaService* GetForProfile(Profile* profile); + static BruschettaServiceFactory* GetInstance(); + + BruschettaServiceFactory(const BruschettaServiceFactory&) = delete; + BruschettaServiceFactory& operator=(const BruschettaServiceFactory&) = delete; + + private: + friend class base::NoDestructor<BruschettaServiceFactory>; + + BruschettaServiceFactory(); + ~BruschettaServiceFactory() override; + + // BrowserContextKeyedServiceFactory: + KeyedService* BuildServiceInstanceFor( + content::BrowserContext* context) const override; +}; + +} // namespace bruschetta + +#endif // CHROME_BROWSER_ASH_BRUSCHETTA_BRUSCHETTA_SERVICE_FACTORY_H_
diff --git a/chrome/browser/ash/child_accounts/family_user_parental_control_metrics_unittest.cc b/chrome/browser/ash/child_accounts/family_user_parental_control_metrics_unittest.cc index 4d26b1a7..bc41d22 100644 --- a/chrome/browser/ash/child_accounts/family_user_parental_control_metrics_unittest.cc +++ b/chrome/browser/ash/child_accounts/family_user_parental_control_metrics_unittest.cc
@@ -63,7 +63,6 @@ package->last_backup_time = 1; package->sync = false; package->system = false; - package->permissions = base::flat_map<::arc::mojom::AppPermission, bool>(); return package; }
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_time_browsertest.cc b/chrome/browser/ash/child_accounts/time_limits/app_time_browsertest.cc index 971b4ba..f0eb011 100644 --- a/chrome/browser/ash/child_accounts/time_limits/app_time_browsertest.cc +++ b/chrome/browser/ash/child_accounts/time_limits/app_time_browsertest.cc
@@ -6,7 +6,6 @@ #include <string> #include "ash/components/arc/mojom/app.mojom.h" -#include "ash/components/arc/mojom/app_permissions.mojom.h" #include "ash/components/arc/test/arc_util_test_support.h" #include "ash/components/arc/test/connection_holder_util.h" #include "ash/components/arc/test/fake_app_instance.h" @@ -54,7 +53,6 @@ package->last_backup_time = 1; package->sync = false; package->system = false; - package->permissions = base::flat_map<::arc::mojom::AppPermission, bool>(); return package; }
diff --git a/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.cc b/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.cc index 3f3b2085..8d5e6b4 100644 --- a/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.cc +++ b/chrome/browser/ash/child_accounts/time_limits/app_time_test_utils.cc
@@ -23,7 +23,6 @@ package->last_backup_time = 1; package->sync = false; package->system = false; - package->permissions = base::flat_map<::arc::mojom::AppPermission, bool>(); return package; }
diff --git a/chrome/browser/ash/chrome_browser_main_parts_ash.cc b/chrome/browser/ash/chrome_browser_main_parts_ash.cc index 8c9d2991..8639f220 100644 --- a/chrome/browser/ash/chrome_browser_main_parts_ash.cc +++ b/chrome/browser/ash/chrome_browser_main_parts_ash.cc
@@ -1042,10 +1042,8 @@ ProfileHelper::GetSigninProfile(); } - if (base::FeatureList::IsEnabled(features::kImeSystemEmojiPicker)) { - ui::SetShowEmojiKeyboardCallback( - base::BindRepeating(&EmojiUI::Show, base::Unretained(profile))); - } + ui::SetShowEmojiKeyboardCallback( + base::BindRepeating(&EmojiUI::Show, base::Unretained(profile))); BootTimesRecorder::Get()->OnChromeProcessStart();
diff --git a/chrome/browser/ash/crosapi/browser_manager.cc b/chrome/browser/ash/crosapi/browser_manager.cc index 6377e12..caf84d4 100644 --- a/chrome/browser/ash/crosapi/browser_manager.cc +++ b/chrome/browser/ash/crosapi/browser_manager.cc
@@ -832,12 +832,18 @@ std::string chrome_path = lacros_path_.MaybeAsASCII() + "/chrome"; LOG(WARNING) << "Launching lacros-chrome at " << chrome_path; - DCHECK(lacros_selection_.has_value()); - version_info::Channel update_channel = - browser_util::GetLacrosSelectionUpdateChannel(lacros_selection_.value()); - // If we don't have channel information, we default to the "dev" channel. - if (update_channel == version_info::Channel::UNKNOWN) - update_channel = browser_util::kLacrosDefaultChannel; + // If Ash is an unknown channel then this is not a production build and we + // should be using an unknown channel for Lacros as well. This prevents Lacros + // from picking up Finch experiments. + version_info::Channel update_channel = version_info::Channel::UNKNOWN; + if (chrome::GetChannel() != version_info::Channel::UNKNOWN) { + DCHECK(lacros_selection_.has_value()); + update_channel = browser_util::GetLacrosSelectionUpdateChannel( + lacros_selection_.value()); + // If we don't have channel information, we default to the "dev" channel. + if (update_channel == version_info::Channel::UNKNOWN) + update_channel = browser_util::kLacrosDefaultChannel; + } base::LaunchOptions options; options.environment["EGL_PLATFORM"] = "surfaceless";
diff --git a/chrome/browser/ash/eche_app/eche_app_notification_controller.cc b/chrome/browser/ash/eche_app/eche_app_notification_controller.cc index 769fe3a5..597a580 100644 --- a/chrome/browser/ash/eche_app/eche_app_notification_controller.cc +++ b/chrome/browser/ash/eche_app/eche_app_notification_controller.cc
@@ -67,8 +67,8 @@ void EcheAppNotificationController::LaunchLearnMore() { // TODO(crbug.com/1241352): Wait for UX confirm. - NewWindowDelegate::GetInstance()->OpenUrl(GURL(kEcheAppLearnMoreUrl), - /* from_user_interaction= */ true); + NewWindowDelegate::GetPrimary()->OpenUrl(GURL(kEcheAppLearnMoreUrl), + /* from_user_interaction= */ true); } void EcheAppNotificationController::LaunchTryAgain() {
diff --git a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc index 5eae4564..07ffd11b 100644 --- a/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc +++ b/chrome/browser/ash/file_manager/file_manager_browsertest_base.cc
@@ -2120,7 +2120,7 @@ if (type) arg_value.SetStringKey("type", *type); std::string search; - if (arg_value.HasKey("currentDirectoryURL") || arg_value.HasKey("type")) { + if (arg_value.FindKey("currentDirectoryURL") || arg_value.FindKey("type")) { std::string json_args; base::JSONWriter::Write(arg_value, &json_args); search = base::StrCat(
diff --git a/chrome/browser/ash/file_manager/file_manager_string_util.cc b/chrome/browser/ash/file_manager/file_manager_string_util.cc index 9097798..fb35cdf5 100644 --- a/chrome/browser/ash/file_manager/file_manager_string_util.cc +++ b/chrome/browser/ash/file_manager/file_manager_string_util.cc
@@ -997,5 +997,8 @@ dict->SetBoolKey("FUSEBOX", base::FeatureList::IsEnabled(chromeos::features::kFuseBox)); + dict->SetBoolKey("GUEST_OS", base::FeatureList::IsEnabled( + chromeos::features::kGuestOsFiles)); + dict->SetStringKey("UI_LOCALE", locale); }
diff --git a/chrome/browser/ash/file_system_provider/fileapi/provider_async_file_util_unittest.cc b/chrome/browser/ash/file_system_provider/fileapi/provider_async_file_util_unittest.cc index 3638000..401eb7a 100644 --- a/chrome/browser/ash/file_system_provider/fileapi/provider_async_file_util_unittest.cc +++ b/chrome/browser/ash/file_system_provider/fileapi/provider_async_file_util_unittest.cc
@@ -61,6 +61,9 @@ } void OnCreateOrOpen(base::File file, base::OnceClosure on_close_callback) { + // ProviderAsyncFileUtil always provides a null `on_close_callback`. + DCHECK(on_close_callback.is_null()); + if (file.IsValid()) result_ = std::make_unique<base::File::Error>(base::File::FILE_OK);
diff --git a/chrome/browser/ash/input_method/input_method_engine.cc b/chrome/browser/ash/input_method/input_method_engine.cc index 056d88f..64f7ec5d 100644 --- a/chrome/browser/ash/input_method/input_method_engine.cc +++ b/chrome/browser/ash/input_method/input_method_engine.cc
@@ -1115,22 +1115,6 @@ if (item.modified & MENU_ITEM_MODIFIED_CHECKED) { property->is_selection_item_checked = item.checked; } - if (item.modified & MENU_ITEM_MODIFIED_STYLE) { - switch (item.style) { - case InputMethodManager::MENU_ITEM_STYLE_NONE: - NOTREACHED(); - break; - case InputMethodManager::MENU_ITEM_STYLE_CHECK: - // TODO(nona): Implement it. - break; - case InputMethodManager::MENU_ITEM_STYLE_RADIO: - property->is_selection_item = true; - break; - case InputMethodManager::MENU_ITEM_STYLE_SEPARATOR: - // TODO(nona): Implement it. - break; - } - } // TODO(nona): Support item.children. }
diff --git a/chrome/browser/ash/input_method/input_method_engine.h b/chrome/browser/ash/input_method/input_method_engine.h index 0c3f00a..957b6a9 100644 --- a/chrome/browser/ash/input_method/input_method_engine.h +++ b/chrome/browser/ash/input_method/input_method_engine.h
@@ -54,7 +54,6 @@ public: enum { MENU_ITEM_MODIFIED_LABEL = 0x0001, - MENU_ITEM_MODIFIED_STYLE = 0x0002, MENU_ITEM_MODIFIED_CHECKED = 0x0010, };
diff --git a/chrome/browser/ash/input_method/input_method_engine_browsertests.cc b/chrome/browser/ash/input_method/input_method_engine_browsertests.cc index 2e7877c..4f8be8b5 100644 --- a/chrome/browser/ash/input_method/input_method_engine_browsertests.cc +++ b/chrome/browser/ash/input_method/input_method_engine_browsertests.cc
@@ -1163,10 +1163,6 @@ EXPECT_EQ("LABEL3", props[3].label); EXPECT_EQ("LABEL4", props[4].label); - EXPECT_TRUE(props[2].is_selection_item); - // TODO(nona): Add tests for style: ["toggle" and "separator"] - // and visible:, when implement them. - EXPECT_TRUE(props[4].is_selection_item_checked); } {
diff --git a/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc b/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc index 86e1025..ecd95a8c 100644 --- a/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc +++ b/chrome/browser/ash/input_method/input_method_manager_impl_unittest.cc
@@ -845,8 +845,7 @@ TEST_F(InputMethodManagerImplTest, TestActivateInputMethodMenuItem) { const std::string kKey = "key"; ui::ime::InputMethodMenuItemList menu_list; - menu_list.push_back(ui::ime::InputMethodMenuItem( - kKey, "label", false, false)); + menu_list.push_back(ui::ime::InputMethodMenuItem(kKey, "label", false)); menu_manager_->SetCurrentInputMethodMenuItemList(menu_list); manager_->ActivateInputMethodMenuItem(kKey); @@ -870,8 +869,8 @@ ImeIdFromEngineId(kNaclMozcUsId), false /* show_message */); ui::ime::InputMethodMenuItemList current_property_list; - current_property_list.push_back(ui::ime::InputMethodMenuItem( - "key", "label", false, false)); + current_property_list.push_back( + ui::ime::InputMethodMenuItem("key", "label", false)); menu_manager_->SetCurrentInputMethodMenuItemList(current_property_list); ASSERT_EQ(1U, menu_manager_->GetCurrentInputMethodMenuItemList().size()); @@ -894,10 +893,8 @@ EXPECT_TRUE(menu_manager_->GetCurrentInputMethodMenuItemList().empty()); ui::ime::InputMethodMenuItemList current_property_list; - current_property_list.push_back(ui::ime::InputMethodMenuItem("key-mozc", - "label", - false, - false)); + current_property_list.push_back( + ui::ime::InputMethodMenuItem("key-mozc", "label", false)); menu_manager_->SetCurrentInputMethodMenuItemList(current_property_list); ASSERT_EQ(1U, menu_manager_->GetCurrentInputMethodMenuItemList().size()); @@ -911,8 +908,8 @@ // Asynchronous property update signal from mozc-chewing. current_property_list.clear(); - current_property_list.push_back(ui::ime::InputMethodMenuItem( - "key-chewing", "label", false, false)); + current_property_list.push_back( + ui::ime::InputMethodMenuItem("key-chewing", "label", false)); menu_manager_->SetCurrentInputMethodMenuItemList(current_property_list); ASSERT_EQ(1U, menu_manager_->GetCurrentInputMethodMenuItemList().size()); EXPECT_EQ("key-chewing",
diff --git a/chrome/browser/ash/input_method/input_method_persistence.cc b/chrome/browser/ash/input_method/input_method_persistence.cc index 90a948ba..0f8a4cc 100644 --- a/chrome/browser/ash/input_method/input_method_persistence.cc +++ b/chrome/browser/ash/input_method/input_method_persistence.cc
@@ -22,8 +22,7 @@ #include "components/user_manager/known_user.h" #include "ui/base/ime/ash/input_method_util.h" -namespace ash { -namespace input_method { +namespace ash::input_method { namespace { void PersistSystemInputMethod(const std::string& input_method) { @@ -48,8 +47,8 @@ const std::string& input_method_id) { if (!account_id.is_valid()) return; - user_manager::known_user::SetUserLastLoginInputMethodId(account_id, - input_method_id); + user_manager::KnownUser known_user(g_browser_process->local_state()); + known_user.SetUserLastLoginInputMethodId(account_id, input_method_id); } void PersistUserInputMethod(const std::string& input_method_id, @@ -148,5 +147,4 @@ SetUserLastInputMethodPreference(account_id, input_method); } -} // namespace input_method -} // namespace ash +} // namespace ash::input_method
diff --git a/chrome/browser/ash/input_method/ui/input_method_menu_item.cc b/chrome/browser/ash/input_method/ui/input_method_menu_item.cc index 5e391b4..7a311f9 100644 --- a/chrome/browser/ash/input_method/ui/input_method_menu_item.cc +++ b/chrome/browser/ash/input_method/ui/input_method_menu_item.cc
@@ -13,24 +13,20 @@ InputMethodMenuItem::InputMethodMenuItem(const std::string& in_key, const std::string& in_label, - bool in_is_selection_item, bool in_is_selection_item_checked) : key(in_key), label(in_label), - is_selection_item(in_is_selection_item), is_selection_item_checked(in_is_selection_item_checked) { DCHECK(!key.empty()); } -InputMethodMenuItem::InputMethodMenuItem() - : is_selection_item(false), is_selection_item_checked(false) {} +InputMethodMenuItem::InputMethodMenuItem() : is_selection_item_checked(false) {} InputMethodMenuItem::~InputMethodMenuItem() {} std::string InputMethodMenuItem::ToString() const { std::stringstream stream; stream << "key=" << key << ", label=" << label - << ", is_selection_item=" << is_selection_item << ", is_selection_item_checked=" << is_selection_item_checked; return stream.str(); }
diff --git a/chrome/browser/ash/input_method/ui/input_method_menu_item.h b/chrome/browser/ash/input_method/ui/input_method_menu_item.h index 6bbce825..9a997d6 100644 --- a/chrome/browser/ash/input_method/ui/input_method_menu_item.h +++ b/chrome/browser/ash/input_method/ui/input_method_menu_item.h
@@ -16,7 +16,6 @@ struct UI_CHROMEOS_EXPORT InputMethodMenuItem { InputMethodMenuItem(const std::string& in_key, const std::string& in_label, - bool in_is_selection_item, bool in_is_selection_item_checked); InputMethodMenuItem(); @@ -29,9 +28,7 @@ // (e.g. "InputMode.HalfWidthKatakana") std::string label; // A description of the property. Non-empty string. // (e.g. "Switch to full punctuation mode", "Hiragana") - bool is_selection_item; // true if the property is a selection item. - bool is_selection_item_checked; // true if |is_selection_item| is true and - // the selection_item is selected. + bool is_selection_item_checked; // true if the selection_item is selected. }; typedef std::vector<InputMethodMenuItem> InputMethodMenuItemList;
diff --git a/chrome/browser/ash/input_method/ui/input_method_menu_manager_unittest.cc b/chrome/browser/ash/input_method/ui/input_method_menu_manager_unittest.cc index 581e1a7..7162989c 100644 --- a/chrome/browser/ash/input_method/ui/input_method_menu_manager_unittest.cc +++ b/chrome/browser/ash/input_method/ui/input_method_menu_manager_unittest.cc
@@ -50,16 +50,16 @@ TEST_F(InputMethodMenuManagerStatefulTest, AddAndCheckExists) { InputMethodMenuItemList list; - list.push_back(InputMethodMenuItem("key1", "label1", false, false)); - list.push_back(InputMethodMenuItem("key2", "label2", false, false)); + list.push_back(InputMethodMenuItem("key1", "label1", false)); + list.push_back(InputMethodMenuItem("key2", "label2", false)); menu_manager_->SetCurrentInputMethodMenuItemList(list); EXPECT_EQ(menu_manager_->GetCurrentInputMethodMenuItemList().size(), 2U); EXPECT_EQ(menu_manager_->GetCurrentInputMethodMenuItemList().at(0).ToString(), "key=key1, label=label1, " - "is_selection_item=0, is_selection_item_checked=0"); + "is_selection_item_checked=0"); EXPECT_EQ(menu_manager_->GetCurrentInputMethodMenuItemList().at(1).ToString(), "key=key2, label=label2, " - "is_selection_item=0, is_selection_item_checked=0"); + "is_selection_item_checked=0"); EXPECT_TRUE(menu_manager_->HasInputMethodMenuItemForKey("key1")); EXPECT_TRUE(menu_manager_->HasInputMethodMenuItemForKey("key2"));
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_service.cc b/chrome/browser/ash/login/easy_unlock/easy_unlock_service.cc index 82d21c1..72c3566c 100644 --- a/chrome/browser/ash/login/easy_unlock/easy_unlock_service.cc +++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_service.cc
@@ -202,6 +202,13 @@ return false; } +SmartLockState EasyUnlockService::GetInitialSmartLockState() const { + if (IsAllowed() && IsEnabled() && proximity_auth_system_ != nullptr) + return SmartLockState::kConnectingToPhone; + + return SmartLockState::kDisabled; +} + void EasyUnlockService::SetHardlockState( SmartLockStateHandler::HardlockState state) { if (base::FeatureList::IsEnabled(ash::features::kSmartLockUIRevamp)) @@ -517,7 +524,9 @@ void EasyUnlockService::OnScreenDidLock( proximity_auth::ScreenlockBridge::LockHandler::ScreenType screen_type) { - // TODO(b/216832183): Show initial Smart Lock state to prevent UI jank. + if (base::FeatureList::IsEnabled(ash::features::kSmartLockUIRevamp)) { + ShowInitialSmartLockState(); + } } void EasyUnlockService::UpdateAppState() { @@ -532,8 +541,30 @@ } } +void EasyUnlockService::ShowInitialSmartLockState() { + // Only proceed if the screen is locked to prevent the UI event from not + // persisting within UpdateSmartLockState(). + // + // Note: ScreenlockBridge::IsLocked() may return a false positive if the + // system is "warming up" (for example, ScreenlockBridge::IsLocked() will + // return false when EasyUnlockServiceSignin is first instantiated because of + // initialization timing in UserSelectionScreen). To work around this race, + // ShowInitialSmartLockState() is also called from OnScreenDidLock() (which + // triggers when ScreenlockBridge::IsLocked() becomes true) to ensure that + // an initial state is displayed in the UI. + auto* screenlock_bridge = proximity_auth::ScreenlockBridge::Get(); + if (screenlock_bridge && screenlock_bridge->IsLocked()) { + UpdateSmartLockState(GetInitialSmartLockState()); + } +} + void EasyUnlockService::ResetSmartLockState() { - smartlock_state_handler_.reset(); + if (base::FeatureList::IsEnabled(ash::features::kSmartLockUIRevamp)) { + smart_lock_state_.reset(); + } else { + smartlock_state_handler_.reset(); + } + auth_attempt_.reset(); } @@ -804,8 +835,16 @@ } void EasyUnlockService::PrepareForSuspend() { - if (smartlock_state_handler_ && smartlock_state_handler_->IsActive()) - UpdateSmartLockState(SmartLockState::kConnectingToPhone); + if (base::FeatureList::IsEnabled(ash::features::kSmartLockUIRevamp)) { + if (smart_lock_state_ && *smart_lock_state_ != SmartLockState::kInactive) { + ShowInitialSmartLockState(); + } + } else { + if (smartlock_state_handler_ && smartlock_state_handler_->IsActive()) { + UpdateSmartLockState(SmartLockState::kConnectingToPhone); + } + } + if (proximity_auth_system_) proximity_auth_system_->OnSuspend(); }
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_service.h b/chrome/browser/ash/login/easy_unlock/easy_unlock_service.h index 22292ec..9b96d70 100644 --- a/chrome/browser/ash/login/easy_unlock/easy_unlock_service.h +++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_service.h
@@ -125,6 +125,18 @@ // Returns true if ChromeOS login is enabled by the user. virtual bool IsChromeOSLoginEnabled() const; + // To be called when EasyUnlockService is "warming up", for example, on screen + // lock, after suspend, when the login screen is starting up, etc. During a + // period like this, not all sub-systems are fully initialized, particularly + // UnlockManager and the Bluetooth stack, so to avoid UI jank, callers can use + // this method to fill in the UI with an approximation of what the UI will + // look like in <1 second. The resulting initial state will be one of two + // possibilities: + // * SmartLockState::kConnectingToPhone: if the feature is allowed, enabled, + // and has kicked off a scan/connection. + // * SmartLockState::kDisabled: if any values above can't be confirmed. + virtual SmartLockState GetInitialSmartLockState() const; + // Sets the hardlock state for the associated user. void SetHardlockState(SmartLockStateHandler::HardlockState state); @@ -214,6 +226,9 @@ // Checks whether Easy unlock should be running and updates app state. void UpdateAppState(); + // Fill in the UI with the state returned by GetInitialSmartLockState(). + void ShowInitialSmartLockState(); + // Resets the Smart Lock state set by this service. void ResetSmartLockState();
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular_unittest.cc b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular_unittest.cc index 7844f0d..4af6fd5 100644 --- a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular_unittest.cc +++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_regular_unittest.cc
@@ -543,4 +543,62 @@ SetScreenLockState(false /* is_locked */); } +TEST_F(EasyUnlockServiceRegularTest, GetInitialSmartLockState_FeatureEnabled) { + base::test::ScopedFeatureList feature_list(features::kSmartLockUIRevamp); + + InitializeService(true /* should_initialize_all_dependencies */); + SetScreenLockState(true /* is_locked */); + + auto* service = + static_cast<EasyUnlockService*>(easy_unlock_service_regular_.get()); + EXPECT_EQ(SmartLockState::kConnectingToPhone, + service->GetInitialSmartLockState()); +} + +TEST_F(EasyUnlockServiceRegularTest, GetInitialSmartLockState_FeatureDisabled) { + base::test::ScopedFeatureList feature_list(features::kSmartLockUIRevamp); + + InitializeService(true /* should_initialize_all_dependencies */); + SetIsEnabled(false); + SetScreenLockState(true /* is_locked */); + + auto* service = + static_cast<EasyUnlockService*>(easy_unlock_service_regular_.get()); + EXPECT_EQ(SmartLockState::kDisabled, service->GetInitialSmartLockState()); +} + +TEST_F(EasyUnlockServiceRegularTest, ShowInitialSmartLockState_FeatureEnabled) { + base::test::ScopedFeatureList feature_list(features::kSmartLockUIRevamp); + + InitializeService(true /* should_initialize_all_dependencies */); + + EXPECT_FALSE(fake_lock_handler_->smart_lock_state()); + + SetScreenLockState(true /* is_locked */); + + // Before EasyUnlockService::UpdateSmartLockState() is called externally, + // ensure that internal state is updated to an "initial" state to prevent + // UI jank. + EXPECT_EQ(SmartLockState::kConnectingToPhone, + fake_lock_handler_->smart_lock_state().value()); +} + +TEST_F(EasyUnlockServiceRegularTest, + ShowInitialSmartLockState_FeatureDisabled) { + base::test::ScopedFeatureList feature_list(features::kSmartLockUIRevamp); + + InitializeService(true /* should_initialize_all_dependencies */); + SetIsEnabled(false); + + EXPECT_FALSE(fake_lock_handler_->smart_lock_state()); + + SetScreenLockState(true /* is_locked */); + + // Before EasyUnlockService::UpdateSmartLockState() is called externally, + // ensure that internal state is updated to an "initial" state to prevent + // UI jank. + EXPECT_EQ(SmartLockState::kDisabled, + fake_lock_handler_->smart_lock_state().value()); +} + } // namespace ash
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_signin.cc b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_signin.cc index d0cebac..7f79065 100644 --- a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_signin.cc +++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_signin.cc
@@ -345,6 +345,13 @@ return pref_manager_ && pref_manager_->IsChromeOSLoginEnabled(); } +SmartLockState EasyUnlockServiceSignin::GetInitialSmartLockState() const { + if (IsChromeOSLoginEnabled()) + return EasyUnlockService::GetInitialSmartLockState(); + + return SmartLockState::kDisabled; +} + void EasyUnlockServiceSignin::OnSuspendDoneInternal() { // Ignored. } @@ -416,7 +423,7 @@ // Update initial UI is when the account picker on login screen is ready. if (base::FeatureList::IsEnabled(ash::features::kSmartLockUIRevamp)) { - // TODO(b/216832183): Show initial Smart Lock state to prevent UI jank. + ShowInitialSmartLockState(); } else { ShowInitialUserPodState(); }
diff --git a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_signin.h b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_signin.h index 0c8d0d5..1bd1115 100644 --- a/chrome/browser/ash/login/easy_unlock/easy_unlock_service_signin.h +++ b/chrome/browser/ash/login/easy_unlock/easy_unlock_service_signin.h
@@ -99,6 +99,7 @@ bool IsEligible() const override; bool IsEnabled() const override; bool IsChromeOSLoginEnabled() const override; + SmartLockState GetInitialSmartLockState() const override; void OnSuspendDoneInternal() override; // EasyUnlockService:
diff --git a/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc b/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc index 260d825..4d7acae 100644 --- a/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc +++ b/chrome/browser/ash/login/enrollment/auto_enrollment_controller.cc
@@ -20,6 +20,7 @@ #include "chrome/browser/ash/policy/enrollment/private_membership/fake_private_membership_rlwe_client.h" #include "chrome/browser/ash/policy/enrollment/private_membership/private_membership_rlwe_client.h" #include "chrome/browser/ash/policy/enrollment/private_membership/private_membership_rlwe_client_impl.h" +#include "chrome/browser/ash/policy/enrollment/private_membership/psm_rlwe_id_provider_impl.h" #include "chrome/browser/ash/policy/server_backed_state/server_backed_state_keys_broker.h" #include "chrome/browser/ash/settings/device_settings_service.h" #include "chrome/browser/browser_process.h" @@ -680,7 +681,7 @@ g_browser_process->system_network_context_manager() ->GetSharedURLLoaderFactory(), serial_number, rlz_brand_code, power_initial, power_limit, - psm_rlwe_client_factory_.get()); + psm_rlwe_client_factory_.get(), &psm_rlwe_id_provider_); LOG(WARNING) << "Starting auto-enrollment client for Initial Enrollment."; client_->Start();
diff --git a/chrome/browser/ash/login/enrollment/auto_enrollment_controller.h b/chrome/browser/ash/login/enrollment/auto_enrollment_controller.h index 5a92863..a3d11b0 100644 --- a/chrome/browser/ash/login/enrollment/auto_enrollment_controller.h +++ b/chrome/browser/ash/login/enrollment/auto_enrollment_controller.h
@@ -14,6 +14,7 @@ #include "base/timer/timer.h" #include "chrome/browser/ash/policy/enrollment/auto_enrollment_client.h" #include "chrome/browser/ash/policy/enrollment/private_membership/private_membership_rlwe_client.h" +#include "chrome/browser/ash/policy/enrollment/private_membership/psm_rlwe_id_provider_impl.h" #include "chrome/browser/ash/settings/device_settings_service.h" #include "chromeos/dbus/cryptohome/UserDataAuth.pb.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -263,6 +264,10 @@ std::unique_ptr<policy::PrivateMembershipRlweClient::Factory> psm_rlwe_client_factory_; + // Constructs the PSM RLWE device ID. + // For more information, see go/psm-rlwe-id-provider. + policy::PsmRlweIdProviderImpl psm_rlwe_id_provider_; + policy::AutoEnrollmentState state_ = policy::AUTO_ENROLLMENT_STATE_IDLE; ProgressCallbackList progress_callbacks_;
diff --git a/chrome/browser/ash/policy/core/user_cloud_policy_store_ash_unittest.cc b/chrome/browser/ash/policy/core/user_cloud_policy_store_ash_unittest.cc index c1c2da32..96e8f89 100644 --- a/chrome/browser/ash/policy/core/user_cloud_policy_store_ash_unittest.cc +++ b/chrome/browser/ash/policy/core/user_cloud_policy_store_ash_unittest.cc
@@ -196,7 +196,7 @@ const PolicyMap::Entry* entry = store_->policy_map().Get(key::kHomepageLocation); ASSERT_TRUE(entry); - EXPECT_TRUE(base::Value(expected_value).Equals(entry->value())); + EXPECT_EQ(base::Value(expected_value), *entry->value()); } // Stores the current |policy_| and verifies that it is published.
diff --git a/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc b/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc index 243e255..41f2f47 100644 --- a/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc +++ b/chrome/browser/ash/policy/dlp/dlp_files_controller_unittest.cc
@@ -129,8 +129,11 @@ testing::Mock::VerifyAndClearExpectations(&add_file_cb); file_url1_ = CreateFileSystemURL(file1.value()); + ASSERT_TRUE(file_url1_.is_valid()); file_url2_ = CreateFileSystemURL(file2.value()); + ASSERT_TRUE(file_url2_.is_valid()); file_url3_ = CreateFileSystemURL(file3.value()); + ASSERT_TRUE(file_url3_.is_valid()); } content::BrowserTaskEnvironment task_environment_; @@ -315,6 +318,7 @@ auto dst_url = mount_points_->CreateExternalFileSystemURL( blink::StorageKey(), mount_name, base::FilePath(path)); + ASSERT_TRUE(dst_url.is_valid()); base::test::TestFuture<std::vector<storage::FileSystemURL>> future; files_controller_.GetDisallowedTransfers(transferred_files, dst_url,
diff --git a/chrome/browser/ash/policy/enrollment/auto_enrollment_client.h b/chrome/browser/ash/policy/enrollment/auto_enrollment_client.h index e01d5ae..1c39fdf 100644 --- a/chrome/browser/ash/policy/enrollment/auto_enrollment_client.h +++ b/chrome/browser/ash/policy/enrollment/auto_enrollment_client.h
@@ -21,6 +21,7 @@ namespace policy { class DeviceManagementService; +class PsmRlweIdProvider; // Indicates the current state of the auto-enrollment check. (Numeric values // are just to make reading of log files easier.) @@ -89,7 +90,8 @@ const std::string& device_brand_code, int power_initial, int power_limit, - PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory) = 0; + PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory, + PsmRlweIdProvider* psm_rlwe_id_provider) = 0; }; virtual ~AutoEnrollmentClient() {}
diff --git a/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl.cc b/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl.cc index fafcfd5..24c5acb 100644 --- a/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl.cc +++ b/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl.cc
@@ -13,9 +13,9 @@ #include "base/memory/ptr_util.h" #include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" -#include "base/strings/string_number_conversions.h" #include "base/threading/thread_task_runner_handle.h" #include "chrome/browser/ash/login/enrollment/auto_enrollment_controller.h" +#include "chrome/browser/ash/policy/enrollment/private_membership/psm_rlwe_id_provider.h" #include "chrome/browser/ash/policy/server_backed_state/server_backed_device_state.h" #include "chrome/common/chrome_content_client.h" #include "chrome/common/pref_names.h" @@ -135,18 +135,6 @@ } // namespace -psm_rlwe::RlwePlaintextId ConstructDeviceRlweId( - const std::string& device_serial_number, - const std::string& device_rlz_brand_code) { - psm_rlwe::RlwePlaintextId rlwe_id; - - std::string rlz_brand_code_hex = base::HexEncode( - device_rlz_brand_code.data(), device_rlz_brand_code.size()); - - rlwe_id.set_sensitive_id(rlz_brand_code_hex + "/" + device_serial_number); - return rlwe_id; -} - class AutoEnrollmentClientImpl::DeviceIdentifierProviderFRE { public: explicit DeviceIdentifierProviderFRE( @@ -218,23 +206,26 @@ // The `psm_result` represents the final result of PSM protocol. using CompletionCallback = base::OnceCallback<void(PsmResult psm_result)>; - // The PsmHelper doesn't take ownership of |device_management_service| and - // |local_state|. Also, both must not be nullptr. The - // |device_management_service| and |local_state| must outlive PsmHelper. + // The PsmHelper doesn't take ownership of |device_management_service|, + // |local_state|, |psm_rlwe_client_factory| and |psm_rlwe_id_provider|. + // All of them must not be nullptr. Also, |device_management_service|, + // and |local_state| must outlive PsmHelper. PsmHelper(DeviceManagementService* device_management_service, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, PrefService* local_state, - psm_rlwe::RlwePlaintextId psm_rlwe_id, - PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory) + PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory, + PsmRlweIdProvider* psm_rlwe_id_provider) : random_device_id_(base::GenerateGUID()), url_loader_factory_(url_loader_factory), device_management_service_(device_management_service), - local_state_(local_state), - psm_rlwe_id_(std::move(psm_rlwe_id)) { + local_state_(local_state) { CHECK(device_management_service); CHECK(psm_rlwe_client_factory); + CHECK(psm_rlwe_id_provider); DCHECK(local_state_); + psm_rlwe_id_ = psm_rlwe_id_provider->ConstructRlweId(); + // Create PSM client for |psm_rlwe_id_| with use case as CROS_DEVICE_STATE. std::vector<psm_rlwe::RlwePlaintextId> psm_ids = {psm_rlwe_id_}; auto status_or_client = psm_rlwe_client_factory->Create( @@ -302,11 +293,6 @@ SendPsmRlweOprfRequest(); } - // Sets the |psm_rlwe_id_| for testing. - void SetRlweIdForTesting(psm_rlwe::RlwePlaintextId psm_rlwe_id) { - psm_rlwe_id_ = std::move(psm_rlwe_id); - } - // Tries to load the result of a previous execution of the PSM protocol from // local state. Returns decision value if it has been made and is valid, // otherwise nullopt. @@ -849,19 +835,18 @@ const std::string& device_brand_code, int power_initial, int power_limit, - PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory) { + PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory, + PsmRlweIdProvider* psm_rlwe_id_provider) { return base::WrapUnique(new AutoEnrollmentClientImpl( progress_callback, device_management_service, local_state, url_loader_factory, /*device_identifier_provider_fre=*/nullptr, std::make_unique<StateDownloadMessageProcessorInitialEnrollment>( device_serial_number, device_brand_code), - power_initial, power_limit, - kUMASuffixInitialEnrollment, - std::make_unique<PsmHelper>( - device_management_service, url_loader_factory, local_state, - ConstructDeviceRlweId(device_serial_number, device_brand_code), - psm_rlwe_client_factory))); + power_initial, power_limit, kUMASuffixInitialEnrollment, + std::make_unique<PsmHelper>(device_management_service, url_loader_factory, + local_state, psm_rlwe_client_factory, + psm_rlwe_id_provider))); } AutoEnrollmentClientImpl::~AutoEnrollmentClientImpl() { @@ -1086,14 +1071,6 @@ } } -void AutoEnrollmentClientImpl::SetPsmRlweIdForTesting( - const psm_rlwe::RlwePlaintextId& psm_rlwe_id) { - if (!psm_helper_) - return; - - psm_helper_->SetRlweIdForTesting(std::move(psm_rlwe_id)); -} - void AutoEnrollmentClientImpl::ReportProgress(AutoEnrollmentState state) { state_ = state; if (progress_callback_.is_null()) {
diff --git a/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl.h b/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl.h index f45d8a3..f2cac1dc 100644 --- a/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl.h +++ b/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl.h
@@ -22,23 +22,13 @@ class PrefRegistrySimple; class PrefService; -namespace private_membership { -namespace rlwe { -class RlwePlaintextId; -} // namespace rlwe -} // namespace private_membership - namespace enterprise_management { class DeviceManagementResponse; } namespace policy { -// Construct the PSM (private set membership) identifier. See -// go/cros-enterprise-psm and go/cros-client-psm for more details. -private_membership::rlwe::RlwePlaintextId ConstructDeviceRlweId( - const std::string& device_serial_number, - const std::string& device_rlz_brand_code); +class PsmRlweIdProvider; // A class that handles all communications related to PSM protocol with // DMServer. Also, upon successful determination, it caches the membership state @@ -108,7 +98,8 @@ const std::string& device_brand_code, int power_initial, int power_limit, - PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory) override; + PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory, + PsmRlweIdProvider* psm_rlwe_id_provider) override; }; AutoEnrollmentClientImpl(const AutoEnrollmentClientImpl&) = delete; @@ -128,11 +119,6 @@ // network::NetworkConnectionTracker::NetworkConnectionObserver: void OnConnectionChanged(network::mojom::ConnectionType type) override; - // Sets the PSM RLWE ID for testing through |psm_helper_|, if the protocol - // is enabled. Also, the |psm_rlwe_client| has to be non-null. - void SetPsmRlweIdForTesting( - const private_membership::rlwe::RlwePlaintextId& psm_rlwe_id); - private: typedef bool (AutoEnrollmentClientImpl::*RequestCompletionHandler)( policy::DeviceManagementService::Job*,
diff --git a/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl_unittest.cc b/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl_unittest.cc index 91079b9..f5f51ae 100644 --- a/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl_unittest.cc +++ b/chrome/browser/ash/policy/enrollment/auto_enrollment_client_impl_unittest.cc
@@ -28,6 +28,7 @@ #include "base/values.h" #include "chrome/browser/ash/login/enrollment/auto_enrollment_controller.h" #include "chrome/browser/ash/policy/enrollment/private_membership/testing_private_membership_rlwe_client.h" +#include "chrome/browser/ash/policy/enrollment/private_membership/testing_psm_rlwe_id_provider.h" #include "chrome/browser/ash/policy/server_backed_state/server_backed_device_state.h" #include "chrome/browser/browser_process.h" #include "chrome/common/pref_names.h" @@ -194,7 +195,8 @@ AutoEnrollmentClientImpl::FactoryImpl().CreateForInitialEnrollment( progress_callback, service_.get(), local_state_, shared_url_loader_factory_, kSerialNumber, kBrandCode, - power_initial, power_limit, psm_rlwe_test_client_factory_.get()); + power_initial, power_limit, psm_rlwe_test_client_factory_.get(), + testing_psm_rlwe_id_provider_.get()); } } @@ -554,6 +556,9 @@ std::unique_ptr<TestingPrivateMembershipRlweClient::FactoryImpl> psm_rlwe_test_client_factory_; + // Sets the PSM RLWE ID directly for testing. + std::unique_ptr<TestingPsmRlweIdProvider> testing_psm_rlwe_id_provider_; + base::HistogramTester histogram_tester_; content::BrowserTaskEnvironment task_environment_{ base::test::TaskEnvironment::TimeSource::MOCK_TIME}; @@ -1671,15 +1676,13 @@ ASSERT_EQ(local_state_->GetUserPref(prefs::kEnrollmentPsmResult), nullptr); // Create PSM test case, before setting up the base class, to construct the - // PSM RLWE testing client factory. + // PSM RLWE testing client factory and its RLWE ID. CreatePsmTestCase(); // Set up the base class AutoEnrollmentClientImplTest after creating the PSM - // RLWE client factory for testing in |psm_rlwe_test_client_factory_|. + // RLWE client factory for testing in |psm_rlwe_test_client_factory_|, and + // PSM RLWE ID provider in |testing_psm_rlwe_id_provider_|. AutoEnrollmentClientImplTest::SetUp(); - - // Override the stored PSM ID in the client. - SetPsmRlweIdClient(); } void CreatePsmTestCase() { @@ -1711,10 +1714,10 @@ std::make_unique<TestingPrivateMembershipRlweClient::FactoryImpl>( psm_test_case_.ec_cipher_key(), psm_test_case_.seed(), plaintext_ids); - } - void SetPsmRlweIdClient() { - client()->SetPsmRlweIdForTesting(psm_test_case_.plaintext_id()); + // Sets the PSM RLWE ID. + testing_psm_rlwe_id_provider_ = std::make_unique<TestingPsmRlweIdProvider>( + psm_test_case_.plaintext_id()); } void ServerWillReplyWithPsmOprfResponse() {
diff --git a/chrome/browser/ash/policy/enrollment/fake_auto_enrollment_client.cc b/chrome/browser/ash/policy/enrollment/fake_auto_enrollment_client.cc index 9ea4376..ba8aa2f 100644 --- a/chrome/browser/ash/policy/enrollment/fake_auto_enrollment_client.cc +++ b/chrome/browser/ash/policy/enrollment/fake_auto_enrollment_client.cc
@@ -40,7 +40,8 @@ const std::string& device_brand_code, int power_initial, int power_limit, - PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory) { + PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory, + PsmRlweIdProvider* psm_rlwe_id_provider) { std::unique_ptr<FakeAutoEnrollmentClient> fake_client = std::make_unique<FakeAutoEnrollmentClient>(progress_callback); fake_client_created_callback_.Run(fake_client.get());
diff --git a/chrome/browser/ash/policy/enrollment/fake_auto_enrollment_client.h b/chrome/browser/ash/policy/enrollment/fake_auto_enrollment_client.h index e2f230d..11f609e 100644 --- a/chrome/browser/ash/policy/enrollment/fake_auto_enrollment_client.h +++ b/chrome/browser/ash/policy/enrollment/fake_auto_enrollment_client.h
@@ -16,6 +16,7 @@ namespace policy { class DeviceManagementService; +class PsmRlweIdProvider; // A fake AutoEnrollmentClient. The test code can control its state. class FakeAutoEnrollmentClient : public AutoEnrollmentClient { @@ -52,8 +53,8 @@ const std::string& device_brand_code, int power_initial, int power_limit, - policy::PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory) - override; + policy::PrivateMembershipRlweClient::Factory* psm_rlwe_client_factory, + PsmRlweIdProvider* psm_rlwe_id_provider) override; private: base::RepeatingCallback<void(FakeAutoEnrollmentClient*)>
diff --git a/chrome/browser/ash/quick_pair/fast_pair_support_utils.cc b/chrome/browser/ash/quick_pair/fast_pair_support_utils.cc new file mode 100644 index 0000000..62e7a27 --- /dev/null +++ b/chrome/browser/ash/quick_pair/fast_pair_support_utils.cc
@@ -0,0 +1,22 @@ +// Copyright 2022 The Chromium 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/ash/quick_pair/fast_pair_support_utils.h" + +#include "ash/constants/ash_features.h" +#include "ash/quick_pair/feature_status_tracker/fast_pair_support_utils.h" +#include "base/bind.h" +#include "device/bluetooth/bluetooth_adapter.h" +#include "google_apis/google_api_keys.h" + +namespace ash { +namespace quick_pair { + +bool IsFastPairSupported(scoped_refptr<device::BluetoothAdapter> adapter) { + return HasHardwareSupport(adapter) && google_apis::HasAPIKeyConfigured() && + google_apis::IsGoogleChromeAPIKeyUsed(); +} + +} // namespace quick_pair +} // namespace ash
diff --git a/chrome/browser/ash/quick_pair/fast_pair_support_utils.h b/chrome/browser/ash/quick_pair/fast_pair_support_utils.h new file mode 100644 index 0000000..add0536f --- /dev/null +++ b/chrome/browser/ash/quick_pair/fast_pair_support_utils.h
@@ -0,0 +1,21 @@ +// Copyright 2022 The Chromium 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_ASH_QUICK_PAIR_FAST_PAIR_SUPPORT_UTILS_H_ +#define CHROME_BROWSER_ASH_QUICK_PAIR_FAST_PAIR_SUPPORT_UTILS_H_ + +#include "base/memory/scoped_refptr.h" +#include "device/bluetooth/bluetooth_adapter.h" + +namespace ash { +namespace quick_pair { + +// Returns true if the device has the minimum requirements to support +// fast pair, such as hardware support and available Google API keys. +bool IsFastPairSupported(scoped_refptr<device::BluetoothAdapter> adapter); + +} // namespace quick_pair +} // namespace ash + +#endif // CHROME_BROWSER_ASH_QUICK_PAIR_FAST_PAIR_SUPPORT_UTILS_H_
diff --git a/chrome/browser/ash/settings/device_settings_provider_unittest.cc b/chrome/browser/ash/settings/device_settings_provider_unittest.cc index aafbd1d..435fd9a 100644 --- a/chrome/browser/ash/settings/device_settings_provider_unittest.cc +++ b/chrome/browser/ash/settings/device_settings_provider_unittest.cc
@@ -641,7 +641,7 @@ // Verify the second change has been applied. const base::Value* saved_value = provider_->Get(kReleaseChannel); - EXPECT_TRUE(value2.Equals(saved_value)); + EXPECT_EQ(value2, *saved_value); Mock::VerifyAndClearExpectations(this); }
diff --git a/chrome/browser/ash/settings/stub_cros_settings_provider_unittest.cc b/chrome/browser/ash/settings/stub_cros_settings_provider_unittest.cc index e893a2e..6ae7c85 100644 --- a/chrome/browser/ash/settings/stub_cros_settings_provider_unittest.cc +++ b/chrome/browser/ash/settings/stub_cros_settings_provider_unittest.cc
@@ -32,7 +32,7 @@ void AssertPref(const std::string& prefName, const base::Value* value) { const base::Value* pref = provider_->Get(prefName); ASSERT_TRUE(pref); - ASSERT_TRUE(pref->Equals(value)); + ASSERT_EQ(*pref, *value); } void ExpectObservers(const std::string& prefName, int count) {
diff --git a/chrome/browser/ash/wallpaper_handlers/wallpaper_handlers.cc b/chrome/browser/ash/wallpaper_handlers/wallpaper_handlers.cc index 135fbb9..83c1945 100644 --- a/chrome/browser/ash/wallpaper_handlers/wallpaper_handlers.cc +++ b/chrome/browser/ash/wallpaper_handlers/wallpaper_handlers.cc
@@ -737,19 +737,18 @@ std::vector<ash::personalization_app::mojom::GooglePhotosPhotoPtr>(); for (const auto& response_photo : response_photos->GetListDeprecated()) { const std::string* id = response_photo.FindStringPath("itemId.mediaKey"); - const std::string* timestamp_seconds_string = - response_photo.FindStringPath("creationTimestamp.seconds"); + const std::string* timestamp_string = + response_photo.FindStringPath("creationTimestamp"); const std::string* url = response_photo.FindStringPath("photo.servingUrl"); - int64_t seconds_after_epoch; - if (!id || !timestamp_seconds_string || - !base::StringToInt64(*timestamp_seconds_string, &seconds_after_epoch) || - seconds_after_epoch < 0 || !url) { + base::Time timestamp; + if (!id || !timestamp_string || + !base::Time::FromUTCString(timestamp_string->c_str(), ×tamp) || + !url) { continue; } - std::u16string date = base::TimeFormatFriendlyDate( - base::Time::UnixEpoch() + base::Seconds(seconds_after_epoch)); + std::u16string date = base::TimeFormatFriendlyDate(timestamp); parsed_response->photos->push_back( ash::personalization_app::mojom::GooglePhotosPhoto::New(*id, date, GURL(*url)));
diff --git a/chrome/browser/ash/web_applications/camera_app/camera_app_untrusted_ui_config.cc b/chrome/browser/ash/web_applications/camera_app/camera_app_untrusted_ui_config.cc new file mode 100644 index 0000000..63cddc95 --- /dev/null +++ b/chrome/browser/ash/web_applications/camera_app/camera_app_untrusted_ui_config.cc
@@ -0,0 +1,25 @@ +// Copyright 2022 The Chromium 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/ash/web_applications/camera_app/camera_app_untrusted_ui_config.h" + +#include <memory> + +#include "ash/webui/camera_app_ui/camera_app_untrusted_ui.h" +#include "ash/webui/camera_app_ui/url_constants.h" +#include "content/public/common/url_constants.h" + +namespace ash { + +CameraAppUntrustedUIConfig::CameraAppUntrustedUIConfig() + : WebUIConfig(content::kChromeUIUntrustedScheme, kChromeUICameraAppHost) {} + +CameraAppUntrustedUIConfig::~CameraAppUntrustedUIConfig() = default; + +std::unique_ptr<content::WebUIController> +CameraAppUntrustedUIConfig::CreateWebUIController(content::WebUI* web_ui) { + return std::make_unique<CameraAppUntrustedUI>(web_ui); +} + +} // namespace ash
diff --git a/chrome/browser/ash/web_applications/camera_app/camera_app_untrusted_ui_config.h b/chrome/browser/ash/web_applications/camera_app/camera_app_untrusted_ui_config.h new file mode 100644 index 0000000..edd78f5 --- /dev/null +++ b/chrome/browser/ash/web_applications/camera_app/camera_app_untrusted_ui_config.h
@@ -0,0 +1,26 @@ +// Copyright 2022 The Chromium 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_ASH_WEB_APPLICATIONS_CAMERA_APP_CAMERA_APP_UNTRUSTED_UI_CONFIG_H_ +#define CHROME_BROWSER_ASH_WEB_APPLICATIONS_CAMERA_APP_CAMERA_APP_UNTRUSTED_UI_CONFIG_H_ + +#include "ui/webui/webui_config.h" + +namespace ash { + +class CameraAppUntrustedUIConfig : public ui::WebUIConfig { + public: + CameraAppUntrustedUIConfig(); + CameraAppUntrustedUIConfig(const CameraAppUntrustedUIConfig& other) = delete; + CameraAppUntrustedUIConfig& operator=(const CameraAppUntrustedUIConfig&) = + delete; + ~CameraAppUntrustedUIConfig() override; + + std::unique_ptr<content::WebUIController> CreateWebUIController( + content::WebUI* web_ui) override; +}; + +} // namespace ash + +#endif // CHROME_BROWSER_ASH_WEB_APPLICATIONS_CAMERA_APP_CAMERA_APP_UNTRUSTED_UI_CONFIG_H_
diff --git a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc index 47ea5aa..62fa171 100644 --- a/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc +++ b/chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl_unittest.cc
@@ -4,9 +4,9 @@ #include "chrome/browser/ash/web_applications/personalization_app/personalization_app_wallpaper_provider_impl.h" -#include <map> #include <memory> #include <string> +#include <utility> #include <vector> #include "ash/constants/ash_features.h" @@ -81,9 +81,7 @@ constexpr char kGooglePhotosPhotosFullResponse[] = "{" " \"item\": [ {" - " \"creationTimestamp\": {" - " \"seconds\": \"60\"" - " }," + " \"creationTimestamp\": \"2021-12-31T07:07:07.000Z\"," " \"itemId\": {" " \"mediaKey\": \"photoId\"" " }," @@ -548,11 +546,13 @@ // Parse one-album responses where one of the album's fields has an invalid // value. - std::map<std::string, std::string> invalid_field_test_cases = { + std::vector<std::pair<std::string, std::string>> invalid_field_test_cases = { + {"numPhotos", ""}, {"numPhotos", "NaN"}, {"numPhotos", "-1"}, {"numPhotos", "0"}, {"coverItemId.mediaKey", "bogusCoverPhotoId"}}; + EXPECT_CALL(*google_photos_albums_fetcher, ParseResponse).Times(5); for (const auto& kv : invalid_field_test_cases) { auto response = base::JSONReader::Read(kGooglePhotosAlbumsFullResponse); auto& album = GetAlbumFromGooglePhotosAlbumsResponse(response); @@ -610,6 +610,11 @@ EXPECT_EQ(-1, google_photos_count_fetcher->ParseResponse( absl::make_optional(response.Clone()))); + // Parse a response with an empty photo count. + response.SetStringPath("user.numPhotos", ""); + EXPECT_EQ(-1, google_photos_count_fetcher->ParseResponse( + absl::make_optional(response.Clone()))); + // Parse a response with a non-integer photo count. response.SetStringPath("user.numPhotos", "NaN"); EXPECT_EQ(-1, google_photos_count_fetcher->ParseResponse( @@ -667,7 +672,7 @@ // Parse one-photo responses where one of the photo's fields is missing. for (const auto* const path : - {"itemId.mediaKey", "creationTimestamp.seconds", "photo.servingUrl"}) { + {"itemId.mediaKey", "creationTimestamp", "photo.servingUrl"}) { auto response = base::JSONReader::Read(kGooglePhotosPhotosFullResponse); auto& photo = GetPhotoFromGooglePhotosPhotosResponse(response); photo.RemovePath(path); @@ -678,9 +683,17 @@ // Parse one-photo responses where one of the photo's fields has an invalid // value. - std::map<std::string, std::string> invalid_field_test_cases = { - {"creationTimestamp.seconds", "NaN"}, - {"creationTimestamp.seconds", "-1"}}; + std::vector<std::pair<std::string, std::string>> invalid_field_test_cases = { + {"creationTimestamp", ""}, + {"creationTimestamp", "Bad timestamp"}, + {"creationTimestamp", "2021T07:07:07.000Z"}, + {"creationTimestamp", "31T07:07:07.000Z"}, + {"creationTimestamp", "12T07:07:07.000Z"}, + {"creationTimestamp", "12-31T07:07:07.000Z"}, + {"creationTimestamp", "2021-31T07:07:07.000Z"}, + {"creationTimestamp", "2021-12T07:07:07.000Z"}, + {"creationTimestamp", "-2021-12-31T07:07:07.000Z"}}; + EXPECT_CALL(*google_photos_photos_fetcher, ParseResponse).Times(9); for (const auto& kv : invalid_field_test_cases) { auto response = base::JSONReader::Read(kGooglePhotosPhotosFullResponse); auto& photo = GetPhotoFromGooglePhotosPhotosResponse(response); @@ -706,12 +719,12 @@ // Ensure that photo timestamps resolve to the same date on all testing // platforms. - icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone("GMT")); + icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone("UTC")); // Parse a response with a valid photo and a resume token. auto valid_photos_vector = std::vector<GooglePhotosPhotoPtr>(); valid_photos_vector.push_back( - GooglePhotosPhoto::New("photoId", u"Thursday, January 1, 1970", + GooglePhotosPhoto::New("photoId", u"Friday, December 31, 2021", GURL("https://www.google.com/"))); EXPECT_EQ(FetchGooglePhotosPhotosResponse::New( mojo::Clone(valid_photos_vector), kResumeToken),
diff --git a/chrome/browser/browser_process.h b/chrome/browser/browser_process.h index 6086ddc..d7b9aa16 100644 --- a/chrome/browser/browser_process.h +++ b/chrome/browser/browser_process.h
@@ -28,6 +28,7 @@ class DownloadRequestLimiter; class DownloadStatusUpdater; class GpuModeManager; +class HidPolicyAllowedDevices; class IconManager; class MediaFileSystemRegistry; class NotificationPlatformBridge; @@ -259,6 +260,10 @@ // Returns the object which keeps track of serial port permissions configured // through the policy engine. virtual SerialPolicyAllowedPorts* serial_policy_allowed_ports() = 0; + + // Returns the object which keeps track of Human Interface Device (HID) + // permissions configured through the policy engine. + virtual HidPolicyAllowedDevices* hid_policy_allowed_devices() = 0; #endif virtual BuildState* GetBuildState() = 0;
diff --git a/chrome/browser/browser_process_impl.cc b/chrome/browser/browser_process_impl.cc index ccc87a0..c414951 100644 --- a/chrome/browser/browser_process_impl.cc +++ b/chrome/browser/browser_process_impl.cc
@@ -164,6 +164,7 @@ #else #include "chrome/browser/devtools/devtools_auto_opener.h" #include "chrome/browser/gcm/gcm_product_util.h" +#include "chrome/browser/hid/hid_policy_allowed_devices.h" #include "chrome/browser/intranet_redirect_detector.h" #include "chrome/browser/resource_coordinator/tab_manager.h" #include "chrome/browser/serial/serial_policy_allowed_ports.h" @@ -935,6 +936,15 @@ } return serial_policy_allowed_ports_.get(); } + +HidPolicyAllowedDevices* BrowserProcessImpl::hid_policy_allowed_devices() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!hid_policy_allowed_devices_) { + hid_policy_allowed_devices_ = + std::make_unique<HidPolicyAllowedDevices>(local_state()); + } + return hid_policy_allowed_devices_.get(); +} #endif BuildState* BrowserProcessImpl::GetBuildState() {
diff --git a/chrome/browser/browser_process_impl.h b/chrome/browser/browser_process_impl.h index 1784761..a40df2a 100644 --- a/chrome/browser/browser_process_impl.h +++ b/chrome/browser/browser_process_impl.h
@@ -214,6 +214,7 @@ #if !BUILDFLAG(IS_ANDROID) SerialPolicyAllowedPorts* serial_policy_allowed_ports() override; + HidPolicyAllowedDevices* hid_policy_allowed_devices() override; #endif BuildState* GetBuildState() override; @@ -426,6 +427,7 @@ base::OnceClosure quit_closure_; std::unique_ptr<SerialPolicyAllowedPorts> serial_policy_allowed_ports_; + std::unique_ptr<HidPolicyAllowedDevices> hid_policy_allowed_devices_; BuildState build_state_; #endif
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager.cc b/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager.cc index 12c554a..c80dcac 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager.cc
@@ -43,6 +43,10 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" +#else +#include "chrome/browser/android/tab_android.h" +#include "chrome/browser/ui/android/tab_model/tab_model.h" +#include "chrome/browser/ui/android/tab_model/tab_model_list.h" #endif namespace { @@ -229,6 +233,14 @@ result.insert(browser->tab_strip_model()->GetWebContentsAt(i)->GetURL()); } } +#else + for (const TabModel* model : TabModelList::models()) { + for (int index = 0; index < model->GetTabCount(); ++index) { + TabAndroid* tab = model->GetTabAt(index); + if (tab) + result.insert(tab->GetURL()); + } + } #endif return result; }
diff --git a/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager_browsertest.cc b/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager_browsertest.cc index f4a98fc..7c12b5f2 100644 --- a/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager_browsertest.cc +++ b/chrome/browser/browsing_data/chrome_browsing_data_lifetime_manager_browsertest.cc
@@ -45,6 +45,7 @@ #include "content/public/browser/browsing_data_remover_delegate.h" #include "content/public/browser/download_manager.h" #include "content/public/browser/storage_partition.h" +#include "content/public/browser/web_contents.h" #include "content/public/common/content_paths.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/browser_test.h" @@ -62,6 +63,10 @@ #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_list.h" #include "chrome/test/base/ui_test_utils.h" +#else +#include "chrome/browser/android/tab_android.h" +#include "chrome/browser/ui/android/tab_model/tab_model.h" +#include "chrome/browser/ui/android/tab_model/tab_model_list.h" #endif namespace { @@ -257,7 +262,6 @@ SetupSiteData(GetActiveWebContents()); ApplyBrowsingDataLifetimeDeletion(kPref); -#if !BUILDFLAG(IS_ANDROID) // The site data is not deleted since the page where it happened is still // opened. CheckSiteData(GetActiveWebContents(), /*has_site_data=*/true); @@ -270,9 +274,7 @@ // active. ApplyBrowsingDataLifetimeDeletion(kPref); ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), url)); -#else - ApplyBrowsingDataLifetimeDeletion(kPref); -#endif + CheckSiteData(GetActiveWebContents(), /*has_site_data=*/false); } @@ -295,7 +297,6 @@ EXPECT_NE(net::OK, content::LoadBasicRequest(network_context(), url)); } -#if !BUILDFLAG(IS_ANDROID) IN_PROC_BROWSER_TEST_P(ChromeBrowsingDataLifetimeManagerScheduledRemovalTest, KeepsOtherTabData) { if (IsIncognito()) @@ -309,10 +310,21 @@ ASSERT_TRUE(content::NavigateToURL(GetActiveWebContents(), url)); auto* first_tab = GetActiveWebContents(); +#if !BUILDFLAG(IS_ANDROID) ui_test_utils::NavigateToURLWithDisposition( browser(), url, WindowOpenDisposition::NEW_FOREGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_LOAD_STOP); + auto* second_tab = GetActiveWebContents(); +#else + TabModel* tab_model = TabModelList::GetTabModelForWebContents(first_tab); + TabAndroid* current_tab = TabAndroid::FromWebContents(first_tab); + std::unique_ptr<content::WebContents> contents = content::WebContents::Create( + content::WebContents::CreateParams(GetProfile())); + auto* second_tab = contents.release(); + tab_model->CreateTab(current_tab, second_tab); + ASSERT_TRUE(content::NavigateToURL(second_tab, url)); +#endif DCHECK_NE(first_tab, second_tab); SetupSiteData(first_tab); @@ -353,8 +365,18 @@ ASSERT_TRUE(content::NavigateToURL(second_tab, url)); CheckSiteData(first_tab, /*has_site_data=*/false); CheckSiteData(second_tab, /*has_site_data=*/false); + +#if BUILDFLAG(IS_ANDROID) + for (int i = 0; i < tab_model->GetTabCount(); ++i) { + if (second_tab == tab_model->GetWebContentsAt(i)) { + tab_model->CloseTabAt(i); + break; + } + } +#endif } +#if !BUILDFLAG(IS_ANDROID) IN_PROC_BROWSER_TEST_P(ChromeBrowsingDataLifetimeManagerScheduledRemovalTest, KeepsOtherWindowData) { if (IsIncognito())
diff --git a/chrome/browser/chrome_browser_interface_binders.cc b/chrome/browser/chrome_browser_interface_binders.cc index 5e8d19f..22c3eff 100644 --- a/chrome/browser/chrome_browser_interface_binders.cc +++ b/chrome/browser/chrome_browser_interface_binders.cc
@@ -969,10 +969,8 @@ map); } - if (base::FeatureList::IsEnabled(chromeos::features::kImeSystemEmojiPicker)) { - RegisterWebUIControllerInterfaceBinder< - emoji_picker::mojom::PageHandlerFactory, chromeos::EmojiUI>(map); - } + RegisterWebUIControllerInterfaceBinder< + emoji_picker::mojom::PageHandlerFactory, chromeos::EmojiUI>(map); if (chromeos::features::IsWallpaperWebUIEnabled()) { RegisterWebUIControllerInterfaceBinder<
diff --git a/chrome/browser/chrome_content_browser_client.cc b/chrome/browser/chrome_content_browser_client.cc index d244ae5..5737196 100644 --- a/chrome/browser/chrome_content_browser_client.cc +++ b/chrome/browser/chrome_content_browser_client.cc
@@ -5810,6 +5810,10 @@ } } +std::string ChromeContentBrowserClient::GetFullUserAgent() { + return embedder_support::GetFullUserAgent(); +} + std::string ChromeContentBrowserClient::GetReducedUserAgent() { return embedder_support::GetReducedUserAgent(); }
diff --git a/chrome/browser/chrome_content_browser_client.h b/chrome/browser/chrome_content_browser_client.h index ebfb1275..9f562aa6 100644 --- a/chrome/browser/chrome_content_browser_client.h +++ b/chrome/browser/chrome_content_browser_client.h
@@ -638,6 +638,7 @@ std::string GetUserAgent() override; std::string GetUserAgentBasedOnPolicy( content::BrowserContext* context) override; + std::string GetFullUserAgent() override; std::string GetReducedUserAgent() override; blink::UserAgentMetadata GetUserAgentMetadata() override;
diff --git a/chrome/browser/chrome_worker_browsertest.cc b/chrome/browser/chrome_worker_browsertest.cc index 486d37f..297d290 100644 --- a/chrome/browser/chrome_worker_browsertest.cc +++ b/chrome/browser/chrome_worker_browsertest.cc
@@ -27,6 +27,16 @@ #include "net/test/embedded_test_server/http_response.h" #include "third_party/re2/src/re2/re2.h" +namespace { + +enum class UserAgentOriginTrialTestType { + UAReduction, + UADeprecation, + UAReductionAndDeprecation +}; + +} // namespace + // A simple fixture used for testing dedicated workers and shared workers. The // fixture stashes the HTTP request to the worker script for inspecting the // headers. @@ -145,7 +155,7 @@ // user agent string if the UserAgentReduction Origin Trial is on. class ChromeWorkerUserAgentBrowserTest : public InProcessBrowserTest, - public testing::WithParamInterface<bool> { + public testing::WithParamInterface<UserAgentOriginTrialTestType> { public: ChromeWorkerUserAgentBrowserTest() = default; @@ -183,19 +193,47 @@ ? "javascript" : "html", "\n"}); - if (WithUserAgentReductionOriginTrialToken()) { - // Generated by running (in tools/origin_trials): - // generate_token.py https://127.0.0.1:44444 UserAgentReduction - // --expire-timestamp=2000000000 - static constexpr char kOriginTrialToken[] = - "A93QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+" - "YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJv" - "cmlnaW4iOiAiaH" - "R0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdl" - "bnRSZWR1Y3Rpb2" - "4iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0="; - base::StrAppend(&headers, - {"Origin-Trial: ", kOriginTrialToken, "\n"}); + + // Generated by running (in tools/origin_trials): + // generate_token.py https://127.0.0.1:44444 UserAgentReduction + // --expire-timestamp=2000000000 + static constexpr char kUAReducedOriginTrialToken[] = + "A93QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+" + "YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJvcm" + "lnaW4iOiAiaH" + "R0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbn" + "RSZWR1Y3Rpb2" + "4iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0="; + + // Generated by running (in tools/origin_trials): + // generate_token.py https://127.0.0.1:44444 + // SendFullUserAgentAfterReduction + // --expire-timestamp=2000000000 + static constexpr char kUAFullOriginTrialToken[] = + "A6+Ti/9KuXTgmFzOQwkTuO8k0QFH8vUaxmv0CllAET1/" + "307KShF6fhskMuBqFUvqO7ViAkZ+" + "NSeJhQI0n5aLggsAAABpeyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6" + "NDQ0NDQiLCAiZmVhdHVyZSI6ICJTZW5kRnVsbFVzZXJBZ2VudEFmdGVyUmVk" + "dWN0aW9uIiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9"; + + switch (GetParam()) { + case UserAgentOriginTrialTestType::UAReduction: + base::StrAppend( + &headers, + {"Origin-Trial: ", kUAReducedOriginTrialToken, "\n"}); + break; + case UserAgentOriginTrialTestType::UADeprecation: + base::StrAppend( + &headers, + {"Origin-Trial: ", kUAFullOriginTrialToken, "\n"}); + break; + case UserAgentOriginTrialTestType::UAReductionAndDeprecation: + base::StrAppend(&headers, + {"Origin-Trial: ", kUAReducedOriginTrialToken, + ",", kUAFullOriginTrialToken, "\n"}); + break; + default: + break; } content::URLLoaderInterceptor::WriteResponse( @@ -205,8 +243,6 @@ })); } - bool WithUserAgentReductionOriginTrialToken() const { return GetParam(); } - void SetExpectedRequestURLs(const std::set<GURL>& expected_request_urls) { expected_request_urls_ = expected_request_urls; } @@ -255,7 +291,8 @@ EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), "waitForMessage()") .ExtractString(), - /*expected_user_agent_reduced=*/WithUserAgentReductionOriginTrialToken()); + /*expected_user_agent_reduced=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction); } IN_PROC_BROWSER_TEST_P(ChromeWorkerUserAgentBrowserTest, @@ -276,7 +313,8 @@ EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), "waitForMessage()") .ExtractString(), - /*expected_user_agent_reduced=*/WithUserAgentReductionOriginTrialToken()); + /*expected_user_agent_reduced=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction); } IN_PROC_BROWSER_TEST_P(ChromeWorkerUserAgentBrowserTest, @@ -302,9 +340,13 @@ EvalJs(browser()->tab_strip_model()->GetActiveWebContents(), "waitForMessage()") .ExtractString(), - /*expected_user_agent_reduced=*/WithUserAgentReductionOriginTrialToken()); + /*expected_user_agent_reduced=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction); } -INSTANTIATE_TEST_SUITE_P(All, - ChromeWorkerUserAgentBrowserTest, - testing::Bool()); +INSTANTIATE_TEST_SUITE_P( + All, + ChromeWorkerUserAgentBrowserTest, + testing::Values(UserAgentOriginTrialTestType::UAReduction, + UserAgentOriginTrialTestType::UADeprecation, + UserAgentOriginTrialTestType::UAReductionAndDeprecation));
diff --git a/chrome/browser/chromeos/BUILD.gn b/chrome/browser/chromeos/BUILD.gn index d809256..8604b01 100644 --- a/chrome/browser/chromeos/BUILD.gn +++ b/chrome/browser/chromeos/BUILD.gn
@@ -116,6 +116,7 @@ "//ash/public/cpp/external_arc", "//ash/public/mojom", "//ash/quick_pair/common", + "//ash/quick_pair/feature_status_tracker", "//ash/services/ime:constants", "//ash/services/ime/public/cpp:structs", "//ash/services/ime/public/mojom", @@ -1167,6 +1168,10 @@ "../ash/browser_accelerator_configuration.h", "../ash/browser_context_keyed_service_factories.cc", "../ash/browser_context_keyed_service_factories.h", + "../ash/bruschetta/bruschetta_service.cc", + "../ash/bruschetta/bruschetta_service.h", + "../ash/bruschetta/bruschetta_service_factory.cc", + "../ash/bruschetta/bruschetta_service_factory.h", "../ash/camera_detector.cc", "../ash/camera_detector.h", "../ash/camera_mic/vm_camera_mic_manager.cc", @@ -2972,6 +2977,8 @@ "../ash/profiles/profile_helper.h", "../ash/psi_memory_metrics.cc", "../ash/psi_memory_metrics.h", + "../ash/quick_pair/fast_pair_support_utils.cc", + "../ash/quick_pair/fast_pair_support_utils.h", "../ash/quick_pair/quick_pair_browser_delegate_impl.cc", "../ash/quick_pair/quick_pair_browser_delegate_impl.h", "../ash/release_notes/release_notes_notification.cc", @@ -3219,6 +3226,8 @@ "../ash/wallpaper_handlers/wallpaper_handlers.h", "../ash/web_applications/calculator_app/calculator_app_utils.cc", "../ash/web_applications/calculator_app/calculator_app_utils.h", + "../ash/web_applications/camera_app/camera_app_untrusted_ui_config.cc", + "../ash/web_applications/camera_app/camera_app_untrusted_ui_config.h", "../ash/web_applications/camera_app/camera_system_web_app_info.cc", "../ash/web_applications/camera_app/camera_system_web_app_info.h", "../ash/web_applications/camera_app/chrome_camera_app_ui_constants.h",
diff --git a/chrome/browser/chromeos/extensions/external_cache_impl.cc b/chrome/browser/chromeos/extensions/external_cache_impl.cc index 5d56754..04eeac2 100644 --- a/chrome/browser/chromeos/extensions/external_cache_impl.cc +++ b/chrome/browser/chromeos/extensions/external_cache_impl.cc
@@ -159,7 +159,7 @@ bool ExternalCacheImpl::ExtensionFetchPending( const extensions::ExtensionId& id) { - return extensions_->HasKey(id) && !cached_extensions_->HasKey(id); + return extensions_->FindKey(id) && !cached_extensions_->FindKey(id); } void ExternalCacheImpl::PutExternalExtension( @@ -190,7 +190,7 @@ const std::set<int>& request_ids, const FailureData& data) { if (error == Error::NO_UPDATE_AVAILABLE) { - if (!cached_extensions_->HasKey(id)) { + if (!cached_extensions_->FindKey(id)) { LOG(ERROR) << "ExternalCacheImpl extension " << id << " not found on update server"; delegate_->OnExtensionDownloadFailed(id);
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc index df1ebb0..b18e8ee3 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_file_system.cc
@@ -1376,7 +1376,7 @@ } for (const auto& hashAndPath : search_results) { - DCHECK(result->HasKey(hashAndPath.hash)); + DCHECK(result->FindKey(hashAndPath.hash)); base::ListValue* list; result->GetListWithoutPathExpansion(hashAndPath.hash, &list); list->Append(hashAndPath.path.value());
diff --git a/chrome/browser/client_hints/client_hints_browsertest.cc b/chrome/browser/client_hints/client_hints_browsertest.cc index 768154e..a9166fec 100644 --- a/chrome/browser/client_hints/client_hints_browsertest.cc +++ b/chrome/browser/client_hints/client_hints_browsertest.cc
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/command_line.h" #include "base/containers/contains.h" +#include "base/containers/fixed_flat_set.h" #include "base/metrics/field_trial_param_associator.h" #include "base/metrics/field_trial_params.h" #include "base/run_loop.h" @@ -210,6 +211,19 @@ } } +enum class UserAgentOriginTrialTestType { + UAReduction, + UADeprecation, + UAReductionAndDeprecation +}; + +struct UserAgentOriginTrialTestOptions { + bool has_ot_token = true; + bool valid_ot_token = true; + bool has_accept_ch_header = true; + bool has_critical_ch_header = false; +}; + } // namespace class ClientHintsBrowserTest : public policy::PolicyTest, @@ -3152,10 +3166,10 @@ EXPECT_EQ(prefers_color_scheme_observed(), "dark"); } -// Base class for the User-Agent reduction Origin Trial browser tests. Common -// functionality shared between the various UA reduction browser tests should -// go in this class. -class UaReducedOriginTrialBrowserTest : public InProcessBrowserTest { +// Base class for the User-Agent reduction or deprecation Origin Trial browser +// tests. Common functionality shared between the various UA browser +// tests should go in this class. +class UaOriginTrialBrowserTest : public InProcessBrowserTest { public: void SetUpCommandLine(base::CommandLine* command_line) override { // The public key for the default privatey key used by the @@ -3185,14 +3199,14 @@ ->SetIsOverridingUserAgent(true); } - void CheckUaReducedClientHint(const bool ch_ua_reduced_expected) { - const absl::optional<std::string>& ua_reduced_client_hint = - GetLastUaReducedClientHintValue(); + void CheckUaOriginTrialClientHint(const bool ch_ua_expected) { + const absl::optional<std::string>& ua_client_hint = + GetLastUaOriginTrialClientHintValue(); - if (ch_ua_reduced_expected) { - EXPECT_THAT(ua_reduced_client_hint, Optional(Eq("?1"))); + if (ch_ua_expected) { + EXPECT_THAT(ua_client_hint, Optional(Eq("?1"))); } else { - EXPECT_THAT(ua_reduced_client_hint, Eq(absl::nullopt)); + EXPECT_THAT(ua_client_hint, Eq(absl::nullopt)); } } @@ -3209,11 +3223,15 @@ expected_user_agent_reduced); } + // |ch_ua_reduced_expected| indicates whether expects a reduce UA string. + // |ch_ua_exist_expected| indicates whether the corresponding + // Sec-CH-UA-Reduced or Sec-CH-UA-Full exist in header. void NavigateAndCheckHeaders(const GURL& url, - const bool ch_ua_reduced_expected) { + const bool ch_ua_reduced_expected, + const bool ch_ua_exist_expected) { ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - CheckUaReducedClientHint(ch_ua_reduced_expected); + CheckUaOriginTrialClientHint(ch_ua_exist_expected); CheckUserAgentReduced(ch_ua_reduced_expected); } @@ -3221,41 +3239,55 @@ // Returns the value of the User-Agent request header from the last sent // request, or nullopt if the header could not be read. virtual const absl::optional<std::string>& GetLastUserAgentHeaderValue() = 0; - // Returns the value of the Sec-CH-UA-Reduced request header from the last - // sent request, or nullopt if the header could not be read. + // Returns the value of the Sec-CH-UA-Reduced or Sec-CH-UA-Full request header + // from the last sent request, or nullopt if the header could not be read. virtual const absl::optional<std::string>& - GetLastUaReducedClientHintValue() = 0; + GetLastUaOriginTrialClientHintValue() = 0; private: base::test::ScopedFeatureList scoped_feature_list_; }; -// Tests that the Sec-CH-UA-Reduced client hint is sent if and only if the +// Common tests that verify +// 1. Sec-CH-UA-Reduced client hint is sent if and only if the // UserAgentReduction Origin Trial token is present and valid in the response // headers. +// 2. Sec-CH-UA-Full client hint is sent if and only if the +// SendFullUserAgentAfterReduction Origin Trial token is present and valid in +// the response headers. // // The test Origin Trial token found in the test files was generated by running // (in tools/origin_trials): // generate_token.py https://127.0.0.1:44444 UserAgentReduction // --expire-timestamp=2000000000 // +// generate_token.py https://127.0.0.1:44444 SendFullUserAgentAfterReduction +// --expire-timestamp=2000000000 +// // The Origin Trial token expires in 2033. Generate a new token by then, or // find a better way to re-generate a test trial token. -class SameOriginUaReducedOriginTrialBrowserTest - : public UaReducedOriginTrialBrowserTest { +class SameOriginUaOriginTrialBrowserTest + : public UaOriginTrialBrowserTest, + public testing::WithParamInterface<UserAgentOriginTrialTestType> { public: - SameOriginUaReducedOriginTrialBrowserTest() = default; + SameOriginUaOriginTrialBrowserTest() = default; // The URL that was used to register the Origin Trial token. static constexpr const char kOriginUrl[] = "https://127.0.0.1:44444"; + // According to the low entropy hint table: + // https://wicg.github.io/client-hints-infrastructure/#low-entropy-hint-table, + // only 3 hints are low entropy hints + static constexpr const int kSecChUaLowEntropyCount = 3; + void SetUpOnMainThread() override { // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since // the origin trial token in the response is associated with a fixed // origin, whereas EmbeddedTestServer serves content on a random port. url_loader_interceptor_ = - URLLoaderInterceptor::ServeFilesFromDirectoryAtOrigin( - "chrome/test/data/client_hints", GURL(kOriginUrl)); + std::make_unique<URLLoaderInterceptor>(base::BindRepeating( + &SameOriginUaOriginTrialBrowserTest::InterceptRequest, + base::Unretained(this))); InProcessBrowserTest::SetUpOnMainThread(); } @@ -3265,6 +3297,12 @@ InProcessBrowserTest::TearDownOnMainThread(); } + void SetTestOptions(const UserAgentOriginTrialTestOptions& test_setting, + const std::set<GURL>& expected_request_urls) { + test_options_ = test_setting; + expected_request_urls_ = expected_request_urls; + } + const absl::optional<std::string>& GetLastUserAgentHeaderValue() override { std::string user_agent; CHECK(url_loader_interceptor_->GetLastRequestHeaders().GetHeader( @@ -3273,82 +3311,115 @@ return last_user_agent_; } - const absl::optional<std::string>& GetLastUaReducedClientHintValue() + const absl::optional<std::string>& GetLastUaOriginTrialClientHintValue() override { - std::string ch_ua_reduced_header_value; + std::string ch_ua_header_value; if (url_loader_interceptor_->GetLastRequestHeaders().GetHeader( - "sec-ch-ua-reduced", &ch_ua_reduced_header_value)) { - last_ua_reduced_ch_ = ch_ua_reduced_header_value; + base::StrCat( + {GetParam() == UserAgentOriginTrialTestType::UAReduction + ? "sec-ch-ua-reduced" + : "sec-ch-ua-full"}), + &ch_ua_header_value)) { + last_ua_ch_val_ = ch_ua_header_value; } else { - last_ua_reduced_ch_ = absl::nullopt; + last_ua_ch_val_ = absl::nullopt; } - return last_ua_reduced_ch_; + return last_ua_ch_val_; } - GURL ua_reduced_with_valid_origin_trial_token_url() const { - return GURL(base::StrCat( - {kOriginUrl, "/accept_ch_ua_reduced_with_valid_origin_trial.html"})); + void CheckSecClientHintUaCount() { + net::HttpRequestHeaders::Iterator header_iterator( + url_loader_interceptor_->GetLastRequestHeaders()); + int sec_ch_ua_count = 0; + while (header_iterator.GetNext()) { + if (base::StartsWith(header_iterator.name(), "sec-ch-ua", + base::CompareCase::SENSITIVE)) { + ++sec_ch_ua_count; + } + } + + if (GetParam() == UserAgentOriginTrialTestType::UAReductionAndDeprecation) { + // Two Accept-CH client hints in header: sec-ch-ua-reduced and + // sec-ch-ua-full. + EXPECT_EQ(sec_ch_ua_count, kSecChUaLowEntropyCount + 2); + } else { + // One Accept-CH client hint in header: sec-ch-ua-reduced or + // sec-ch-ua-full. + EXPECT_EQ(sec_ch_ua_count, kSecChUaLowEntropyCount + 1); + } } - GURL ua_reduced_with_invalid_origin_trial_token_url() const { - return GURL(base::StrCat( - {kOriginUrl, "/accept_ch_ua_reduced_with_invalid_origin_trial.html"})); + void VerifyNonAcceptCHNotAddedToHeader(const std::string& client_hint) { + ASSERT_FALSE(url_loader_interceptor_->GetLastRequestHeaders().HasHeader( + client_hint)); } - GURL ua_reduced_with_no_origin_trial_token_url() const { + GURL ua_with_valid_origin_trial_token_url() const { return GURL(base::StrCat( - {kOriginUrl, "/accept_ch_ua_reduced_with_no_origin_trial.html"})); + {kOriginUrl, "/accept_ch_ua_with_valid_origin_trial.html"})); } - GURL ua_reduced_missing_with_valid_origin_trial_token_url() const { + GURL ua_with_invalid_origin_trial_token_url() const { return GURL(base::StrCat( - {kOriginUrl, "/accept_ch_ua_reduced_missing_valid_origin_trial.html"})); + {kOriginUrl, "/accept_ch_ua_with_invalid_origin_trial.html"})); } - GURL critical_ch_ua_reduced_with_valid_origin_trial_token_url() const { - return GURL(base::StrCat( - {kOriginUrl, "/critical_ch_ua_reduced_with_valid_origin_trial.html"})); + GURL ua_with_no_origin_trial_token_url() const { + return GURL( + base::StrCat({kOriginUrl, "/accept_ch_ua_with_no_origin_trial.html"})); } - GURL critical_ch_ua_reduced_with_invalid_origin_trial_token_url() const { + GURL ua_missing_with_valid_origin_trial_token_url() const { return GURL(base::StrCat( - {kOriginUrl, - "/critical_ch_ua_reduced_with_invalid_origin_trial.html"})); + {kOriginUrl, "/accept_ch_ua_missing_valid_origin_trial.html"})); } - GURL accept_ch_ua_reduced_subresource_request_url() const { + GURL critical_ch_ua_with_valid_origin_trial_token_url() const { return GURL(base::StrCat( - {kOriginUrl, "/accept_ch_ua_reduced_subresource_request.html"})); + {kOriginUrl, "/critical_ch_ua_with_valid_origin_trial.html"})); } - GURL accept_ch_ua_reduced_iframe_request_url() const { + GURL critical_ch_ua_with_invalid_origin_trial_token_url() const { return GURL(base::StrCat( - {kOriginUrl, "/accept_ch_ua_reduced_iframe_request.html"})); + {kOriginUrl, "/critical_ch_ua_with_invalid_origin_trial.html"})); } - GURL critical_ch_ua_reduced_subresource_request_url() const { - return GURL(base::StrCat( - {kOriginUrl, "/critical_ch_ua_reduced_subresource_request.html"})); + GURL accept_ch_ua_subresource_request_url() const { + return GURL( + base::StrCat({kOriginUrl, "/accept_ch_ua_subresource_request.html"})); } - GURL critical_ch_ua_reduced_iframe_request_url() const { - return GURL(base::StrCat( - {kOriginUrl, "/critical_ch_ua_reduced_iframe_request.html"})); + GURL accept_ch_ua_iframe_request_url() const { + return GURL( + base::StrCat({kOriginUrl, "/accept_ch_ua_iframe_request.html"})); + } + + GURL critical_ch_ua_subresource_request_url() const { + return GURL( + base::StrCat({kOriginUrl, "/critical_ch_ua_subresource_request.html"})); + } + + GURL critical_ch_ua_iframe_request_url() const { + return GURL( + base::StrCat({kOriginUrl, "/critical_ch_ua_iframe_request.html"})); } GURL simple_request_url() const { return GURL(base::StrCat({kOriginUrl, "/simple.html"})); } + GURL style_css_request_url() const { + return GURL(base::StrCat({kOriginUrl, "/style.css"})); + } + GURL last_request_url() const { return url_loader_interceptor_->GetLastRequestURL(); } - void VerifyNonAcceptCHNotAddedToHeader() {} - - void NavigateTwiceAndCheckHeader(const GURL& url, - const bool ch_ua_reduced_expected, - const bool critical_ch_ua_reduced_expected) { + void NavigateTwiceAndCheckHeaderReduced( + const GURL& url, + const bool ch_ua_reduced_expected, + const bool critical_ch_ua_reduced_expected) { base::HistogramTester histograms; int reduced_count = 0; int full_count = 0; @@ -3358,7 +3429,8 @@ // Sec-CH-UA-Reduced in the first navigation request. const bool first_navigation_reduced_ua = critical_ch_ua_reduced_expected && ch_ua_reduced_expected; - NavigateAndCheckHeaders(url, first_navigation_reduced_ua); + NavigateAndCheckHeaders(url, first_navigation_reduced_ua, + first_navigation_reduced_ua); if (first_navigation_reduced_ua) { ++reduced_count; if (critical_ch_ua_reduced_expected) { @@ -3381,12 +3453,12 @@ // Regardless of the Critical-CH setting, we expect the Sec-CH-UA-Reduced // client hint sent on the second request, if Sec-CH-UA-Reduced is set and // the Origin Trial token is valid. - NavigateAndCheckHeaders(url, ch_ua_reduced_expected); + NavigateAndCheckHeaders(url, ch_ua_reduced_expected, + ch_ua_reduced_expected); // Make sure non-default client hints are not added to the request headers // of subresource requests. Here, we just use Sec-CH-UA-Bitness as a high // entropy hint to check against. - ASSERT_FALSE(url_loader_interceptor_->GetLastRequestHeaders().HasHeader( - "sec-ch-ua-bitness")); + VerifyNonAcceptCHNotAddedToHeader("sec-ch-ua-bitness"); if (ch_ua_reduced_expected) { ++reduced_count; } else { @@ -3400,48 +3472,240 @@ reduced_count); } + void NavigateTwiceAndCheckHeaderFull( + const GURL& url, + const bool ch_ua_full_expected, + const bool critical_ch_ua_full_expected) { + base::HistogramTester histograms; + int full_count = 0; + + // If Critical-CH is set, we expect Sec-CH-UA-Full in the first + // navigation request header. If Critical-CH is not set, we don't expect + // Sec-CH-UA-Full in the first navigation request. + const bool first_navigation_full_ua = + critical_ch_ua_full_expected && ch_ua_full_expected; + // For full user agent, we never expect the ua reduced. + NavigateAndCheckHeaders(url, false, first_navigation_full_ua); + + // TODO: Currently no matter whether it's a first navigation request or not, + // we always sent the full user agent string. We need to update the count + // logic once we fully migrate to the reduced user agent string. + + // If Critical-CH was set, there will also be the initial navigation + // that send full UA string. + if (critical_ch_ua_full_expected) { + ++full_count; + } + ++full_count; + + // The UserAgentStringType enum is not accessible in //chrome/browser, so + // we just use the enum's integer value. + histograms.ExpectBucketCount("Navigation.UserAgentStringType", + /*NavigationRequest::kFullVersion*/ 0, + full_count); + + // Regardless of the Critical-CH setting, we expect the Sec-CH-UA-Full + // client hint sent on the second request, if Sec-CH-UA-Full is set and + // the Origin Trial token is valid. + NavigateAndCheckHeaders(url, false, ch_ua_full_expected); + // Make sure non-default client hints are not added to the request headers + // of subresource requests. Here, we just use Sec-CH-UA-Bitness as a high + // entropy hint to check against. + VerifyNonAcceptCHNotAddedToHeader("sec-ch-ua-bitness"); + + ++full_count; + histograms.ExpectBucketCount("Navigation.UserAgentStringType", + /*NavigationRequest::kFullVersion*/ 0, + full_count); + } + + void NavigateTwiceAndCheckHeader(const GURL& url, + const bool ch_ua_exist_expected, + const bool critical_ch_ua_exist_expected) { + if (GetParam() == UserAgentOriginTrialTestType::UAReduction) { + NavigateTwiceAndCheckHeaderReduced(url, ch_ua_exist_expected, + critical_ch_ua_exist_expected); + } else { + NavigateTwiceAndCheckHeaderFull(url, ch_ua_exist_expected, + critical_ch_ua_exist_expected); + } + } + private: + // URLLoaderInterceptor callback + bool InterceptRequest(URLLoaderInterceptor::RequestParams* params) { + if (expected_request_urls_.find(params->url_request.url) == + expected_request_urls_.end()) + return false; + + std::string path = "chrome/test/data/client_hints"; + path.append(static_cast<std::string>(params->url_request.url.path_piece())); + + if (params->url_request.url.path() == "/style.css" || + params->url_request.url.path() == "/simple.html") { + URLLoaderInterceptor::WriteResponse(path, params->client.get()); + return true; + } + std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/html\n"; + base::StrAppend(&headers, {BuildOriginTrailHeader()}); + URLLoaderInterceptor::WriteResponse(path, params->client.get(), &headers, + absl::nullopt, + /*url=*/params->url_request.url); + return true; + } + + std::string BuildOriginTrailHeader() { + std::string headers; + + // Generated by running (in tools/origin_trials): + // generate_token.py https://127.0.0.1:44444 UserAgentReduction + // --expire-timestamp=2000000000 + static constexpr char kUAReducedOriginTrialToken[] = + "A93QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+" + "YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJvcm" + "lnaW4iOiAiaH" + "R0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbn" + "RSZWR1Y3Rpb2" + "4iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0="; + + // Generated by running (in tools/origin_trials): + // generate_token.py https://127.0.0.1:44444 + // SendFullUserAgentAfterReduction + // --expire-timestamp=2000000000 + static constexpr char kUAFullOriginTrialToken[] = + "A6+Ti/9KuXTgmFzOQwkTuO8k0QFH8vUaxmv0CllAET1/" + "307KShF6fhskMuBqFUvqO7ViAkZ+" + "NSeJhQI0n5aLggsAAABpeyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6" + "NDQ0NDQiLCAiZmVhdHVyZSI6ICJTZW5kRnVsbFVzZXJBZ2VudEFmdGVyUmVk" + "dWN0aW9uIiwgImV4cGlyeSI6IDIwMDAwMDAwMDB9"; + + switch (GetParam()) { + case UserAgentOriginTrialTestType::UAReduction: + if (test_options_.has_accept_ch_header) { + base::StrAppend(&headers, {"Accept-CH: ", "sec-ch-ua-reduced", "\n"}); + } + if (test_options_.has_critical_ch_header) { + base::StrAppend(&headers, + {"Critical-CH: ", "sec-ch-ua-reduced", "\n"}); + } + if (test_options_.has_ot_token) { + base::StrAppend(&headers, {"Origin-Trial: ", + test_options_.valid_ot_token + ? kUAReducedOriginTrialToken + : "invalid", + "\n"}); + } + break; + case UserAgentOriginTrialTestType::UADeprecation: + if (test_options_.has_accept_ch_header) { + base::StrAppend(&headers, {"Accept-CH: ", "sec-ch-ua-full", "\n"}); + } + if (test_options_.has_critical_ch_header) { + base::StrAppend(&headers, {"Critical-CH: ", "sec-ch-ua-full", "\n"}); + } + if (test_options_.has_ot_token) { + base::StrAppend( + &headers, {"Origin-Trial: ", + test_options_.valid_ot_token ? kUAFullOriginTrialToken + : "invalid", + "\n"}); + } + break; + case UserAgentOriginTrialTestType::UAReductionAndDeprecation: + if (test_options_.has_accept_ch_header) { + base::StrAppend( + &headers, + {"Accept-CH: ", "sec-ch-ua-reduced, sec-ch-ua-full", "\n"}); + } + if (test_options_.has_critical_ch_header) { + base::StrAppend( + &headers, + {"Critical-CH: ", "sec-ch-ua-reduced, sec-ch-ua-full", "\n"}); + } + + if (test_options_.has_ot_token) { + base::StrAppend( + &headers, + {"Origin-Trial: ", + (test_options_.valid_ot_token ? kUAReducedOriginTrialToken + : "invalid"), + ",", + (test_options_.valid_ot_token ? kUAFullOriginTrialToken + : "invalid"), + "\n"}); + } + break; + default: + break; + } + return headers; + } + std::unique_ptr<URLLoaderInterceptor> url_loader_interceptor_; absl::optional<std::string> last_user_agent_; - absl::optional<std::string> last_ua_reduced_ch_; + absl::optional<std::string> last_ua_ch_val_; + std::set<GURL> expected_request_urls_; + UserAgentOriginTrialTestOptions test_options_; }; -constexpr const char SameOriginUaReducedOriginTrialBrowserTest::kOriginUrl[]; +INSTANTIATE_TEST_SUITE_P( + All, + SameOriginUaOriginTrialBrowserTest, + testing::Values(UserAgentOriginTrialTestType::UAReduction, + UserAgentOriginTrialTestType::UADeprecation, + UserAgentOriginTrialTestType::UAReductionAndDeprecation)); -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, - AcceptChUaReducedWithValidOriginTrialToken) { - NavigateTwiceAndCheckHeader(ua_reduced_with_valid_origin_trial_token_url(), - /*ch_ua_reduced_expected=*/true, - /*critical_ch_ua_reduced_expected=*/false); +constexpr const char SameOriginUaOriginTrialBrowserTest::kOriginUrl[]; +constexpr const int SameOriginUaOriginTrialBrowserTest::kSecChUaLowEntropyCount; - // The Origin Trial token is valid, so we expect the reduced UA values in the - // Javascript getters as well. +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, + AcceptChUaWithValidOriginTrialToken) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {ua_with_valid_origin_trial_token_url()}); + + NavigateTwiceAndCheckHeader(ua_with_valid_origin_trial_token_url(), + /*ch_ua_exist_expected=*/true, + /*critical_ch_ua_exist_expected=*/false); + + // The Origin Trial token is valid, so we expect the reduced/full UA values in + // the Javascript getters as well. content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); CheckUserAgentMinorVersion( content::EvalJs(web_contents, "navigator.userAgent").ExtractString(), - /*expected_user_agent_reduced=*/true); + /*expected_user_agent_reduced=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction); CheckUserAgentMinorVersion( content::EvalJs(web_contents, "navigator.appVersion").ExtractString(), - /*expected_user_agent_reduced=*/true); + /*expected_user_agent_reduced=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction); // Instead of checking all platform types, just check one that has a // difference between the full and reduced versions. #if BUILDFLAG(IS_ANDROID) EXPECT_EQ("Linux x86_64", content::EvalJs(web_contents, "navigator.platform")); #endif + + CheckSecClientHintUaCount(); } -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, - AcceptChUaReducedWithInvalidOriginTrialToken) { - // The response contained Sec-CH-UA-Reduced in the Accept-CH header, but the - // origin trial token is invalid. - NavigateTwiceAndCheckHeader(ua_reduced_with_invalid_origin_trial_token_url(), - /*ch_ua_reduced_expected=*/false, - /*critical_ch_ua_reduced_expected=*/false); +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, + AcceptChUaWithInvalidOriginTrialToken) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/false, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {ua_with_invalid_origin_trial_token_url()}); - // The Origin Trial token is invalid, so we expect the full UA values in the - // Javascript getters. + // The response contained Sec-CH-UA-Reduced or Sec-CH-UA-Full in the + // Accept-CH header, but the origin trial token is invalid. + NavigateTwiceAndCheckHeader(ua_with_invalid_origin_trial_token_url(), + /*ch_ua_exist_expected=*/false, + /*critical_ch_ua_exist_expected=*/false); + + // The Origin Trial token is invalid, so we expect the full UA values in + // the Javascript getters. content::WebContents* web_contents = browser()->tab_strip_model()->GetActiveWebContents(); CheckUserAgentMinorVersion( @@ -3458,117 +3722,182 @@ #endif } -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, - AcceptChUaReducedWithNoOriginTrialToken) { - // The response contained Sec-CH-UA-Reduced in the Accept-CH header, but the - // origin trial token is not present. - NavigateTwiceAndCheckHeader(ua_reduced_with_no_origin_trial_token_url(), - /*ch_ua_reduced_expected=*/false, - /*critical_ch_ua_reduced_expected=*/false); +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, + AcceptChUaWithNoOriginTrialToken) { + SetTestOptions( + {/*has_ot_token=*/false, /*valid_ot_token=*/false, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {ua_with_no_origin_trial_token_url()}); + + // The response contained Sec-CH-UA-Reduced or Sec-CH-UA-Full in the + // Accept-CH header, but the origin trial token is not present. + NavigateTwiceAndCheckHeader(ua_with_no_origin_trial_token_url(), + /*ch_ua_exist_expected=*/false, + /*critical_ch_ua_exist_expected=*/false); } -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, - NoAcceptChUaReducedWithValidOriginTrialToken) { - // The response contained a valid Origin Trial token, but no Sec-CH-UA-Reduced - // in the Accept-CH header. - NavigateTwiceAndCheckHeader( - ua_reduced_missing_with_valid_origin_trial_token_url(), - /*ch_ua_reduced_expected=*/false, - /*critical_ch_ua_reduced_expected=*/false); +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, + NoAcceptChUaWithValidOriginTrialToken) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/false, /*has_critical_ch_header=*/false}, + {ua_missing_with_valid_origin_trial_token_url()}); + + // The response contained a valid Origin Trial token, but no corresponding + // Sec-CH-UA-Reduced or Sec-CH-UA-Full in the Accept-CH header. + NavigateTwiceAndCheckHeader(ua_missing_with_valid_origin_trial_token_url(), + /*ch_ua_exist_expected=*/false, + /*critical_ch_ua_exist_expected=*/false); } -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, - CriticalChUaReducedWithValidOriginTrialToken) { +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, + CriticalChUaWithValidOriginTrialToken) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/true}, + {critical_ch_ua_with_valid_origin_trial_token_url()}); + // The initial navigation also contains the Critical-CH header, so the - // Sec-CH-UA-Reduced header should be set after the first navigation. + // corresponding Sec-CH-UA-Reduced or Sec-CH-UA-Full header should be set + // after the first navigation. NavigateTwiceAndCheckHeader( - critical_ch_ua_reduced_with_valid_origin_trial_token_url(), - /*ch_ua_reduced_expected=*/true, - /*critical_ch_ua_reduced_expected=*/true); + critical_ch_ua_with_valid_origin_trial_token_url(), + /*ch_ua_exist_expected=*/true, + /*critical_ch_ua_exist_expected=*/true); + + CheckSecClientHintUaCount(); } -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, - CriticalChUaReducedWithInvalidOriginTrialToken) { +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, + CriticalChUaWithInvalidOriginTrialToken) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/false, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/true}, + {critical_ch_ua_with_invalid_origin_trial_token_url()}); + // The Origin Trial token is invalid, so the Critical-CH should not have - // resulted in the Sec-CH-UA-Reduced header being sent. + // resulted in the corresponding Sec-CH-UA-Reduced or Sec-CH-UA-Full header + // being sent. NavigateTwiceAndCheckHeader( - critical_ch_ua_reduced_with_invalid_origin_trial_token_url(), - /*ch_ua_reduced_expected=*/false, - /*critical_ch_ua_reduced_expected=*/false); + critical_ch_ua_with_invalid_origin_trial_token_url(), + /*ch_ua_exist_expected=*/false, + /*critical_ch_ua_exist_expected=*/false); } -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, - IframeRequestUaReducedWithValidOriginTrialToken) { +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, + IframeRequestUaWithValidOriginTrialToken) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {accept_ch_ua_iframe_request_url(), simple_request_url()}); + // The last resource request processed for this navigation will be an embedded - // iframe request. Since Accept-CH has Sec-CH-UA-Reduced set on the top-level - // level frame's response header, along with a valid origin trial token, the - // iframe request should send Sec-CH-UA-Reduced and the reduced UA string in - // the request header. - NavigateAndCheckHeaders(accept_ch_ua_reduced_iframe_request_url(), - /*ch_ua_reduced_expected=*/true); + // iframe request. Since Accept-CH has either Sec-CH-UA-Reduced or + // Sec-CH-UA-Full set on the top-level level frame's response header, along + // with a valid origin trial token, the iframe request should send the reduced + // UA string if Sec-CH-UA-Reduced set, or the full UA string if Sec-CH-UA-Full + // set in the request header. + NavigateAndCheckHeaders(accept_ch_ua_iframe_request_url(), + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); + + CheckSecClientHintUaCount(); + // Make sure the last intercepted URL was the request for the embedded iframe. EXPECT_EQ(last_request_url().path(), "/simple.html"); } -IN_PROC_BROWSER_TEST_F( - SameOriginUaReducedOriginTrialBrowserTest, - IframeRequestUaReducedWithValidOriginTrialTokenAndCriticalCH) { +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, + IframeRequestUaWithValidOriginTrialTokenAndCriticalCH) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/true}, + {critical_ch_ua_iframe_request_url(), simple_request_url()}); + // The last resource request processed for this navigation will be an embedded - // iframe request. Since Accept-CH has Sec-CH-UA-Reduced set on the top-level - // level frame's response header, along with a valid origin trial token, the - // iframe request should send Sec-CH-UA-Reduced and the reduced UA string in - // the request header. - NavigateAndCheckHeaders(critical_ch_ua_reduced_iframe_request_url(), - /*ch_ua_reduced_expected=*/true); + // iframe request. Since Accept-CH has either Sec-CH-UA-Reduced or + // Sec-CH-UA-Full set on the top-level level frame's response header, + // along with a valid origin trial token, the iframe request should send the + // reduced UA string if Sec-CH-UA-Reduced set, or the full UA string if + // Sec-CH-UA-Full set in the request header. + NavigateAndCheckHeaders(critical_ch_ua_iframe_request_url(), + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); + + CheckSecClientHintUaCount(); + // Make sure the last intercepted URL was the request for the embedded iframe. EXPECT_EQ(last_request_url().path(), "/simple.html"); } -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, - SubresourceRequestUaReducedWithValidOriginTrialToken) { +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, + SubresourceRequestUaWithValidOriginTrialToken) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {accept_ch_ua_subresource_request_url(), style_css_request_url()}); + // The last resource request processed for this navigation will be a // subresource request for the stylesheet. Since Accept-CH has - // Sec-CH-UA-Reduced set on the top-level level frame's response header, along - // with a valid origin trial token, the subresource request should send - // Sec-CH-UA-Reduced and the reduced UA string in the request header. - NavigateAndCheckHeaders(accept_ch_ua_reduced_subresource_request_url(), - /*ch_ua_reduced_expected=*/true); + // either Sec-CH-UA-Reduced or Sec-CH-UA-Full set on the top-level + // level frame's response header, along with a valid origin trial token, the + // subresource request should send the reduced UA string if Sec-CH-UA-Reduced + // set, or the full UA string if Sec-CH-UA-Full set in the request header. + NavigateAndCheckHeaders(accept_ch_ua_subresource_request_url(), + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); // Make sure the last intercepted URL was the subresource request for the // embedded stylesheet. EXPECT_EQ(last_request_url().path(), "/style.css"); } -IN_PROC_BROWSER_TEST_F( - SameOriginUaReducedOriginTrialBrowserTest, - SubresourceRequestUaReducedWithValidOriginTrialTokenAndCriticalCH) { +IN_PROC_BROWSER_TEST_P( + SameOriginUaOriginTrialBrowserTest, + SubresourceRequestUaWithValidOriginTrialTokenAndCriticalCH) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/true}, + {critical_ch_ua_subresource_request_url(), style_css_request_url()}); + // The last resource request processed for this navigation will be a // subresource request for the stylesheet. Since Accept-CH has - // Sec-CH-UA-Reduced set on the top-level level frame's response header, along - // with a valid origin trial token, the subresource request should send - // Sec-CH-UA-Reduced and the reduced UA string in the request header. - NavigateAndCheckHeaders(critical_ch_ua_reduced_subresource_request_url(), - /*ch_ua_reduced_expected=*/true); + // either Sec-CH-UA-Reduced or Sec-CH-UA-Full set on the top-level level + // frame's response header, along with a valid origin trial token, the + // subresource request should send the reduced UA string Sec-CH-UA-Reduced + // set, or the full UA string if Sec-CH-UA-Full set in the request header. + NavigateAndCheckHeaders(critical_ch_ua_subresource_request_url(), + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); // Make sure the last intercepted URL was the subresource request for the // embedded stylesheet. EXPECT_EQ(last_request_url().path(), "/style.css"); } -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, - UserAgentOverrideAcceptChUaReduced) { +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, + UserAgentOverrideAcceptChUa) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {ua_with_valid_origin_trial_token_url()}); + base::HistogramTester histograms; const std::string user_agent_override = "foo"; SetUserAgentOverride(user_agent_override); - const GURL url = ua_reduced_with_valid_origin_trial_token_url(); + const GURL url = ua_with_valid_origin_trial_token_url(); // First navigation to set the client hints in the response. ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - // Second navigation has the Sec-CH-UA-Reduced client hint stored from the - // first navigation's response. + // Second navigation has either Sec-CH-UA-Reduced or Sec-CH-UA-Full client + // hint stored from the first navigation's response. ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); // Since the UA override was set, the UA client hints are *not* added to the // request. - CheckUaReducedClientHint(/*ch_ua_reduced_expected=*/false); + CheckUaOriginTrialClientHint(/*ch_ua_expected=*/false); // Make sure the overridden UA string is the one sent. CheckUserAgentString(user_agent_override); @@ -3578,73 +3907,94 @@ /*NavigationRequest::kOverridden*/ 2, 2); } -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, UserAgentOverrideSubresourceRequest) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {accept_ch_ua_subresource_request_url()}); + const std::string user_agent_override = "foo"; SetUserAgentOverride(user_agent_override); - const GURL url = accept_ch_ua_reduced_subresource_request_url(); + const GURL url = accept_ch_ua_subresource_request_url(); // First navigation to set the client hints in the response. ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - // Second navigation has the Sec-CH-UA-Reduced client hint stored from the - // first navigation's response. + // Second navigation has either Sec-CH-UA-Reduced or Sec-CH-UA-Full client + // hint stored from the first navigation's response. ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); // Since the UA override was set, the UA client hints are *not* added to the // request. - CheckUaReducedClientHint(/*ch_ua_reduced_expected=*/false); + CheckUaOriginTrialClientHint(/*ch_ua_expected=*/false); // Make sure the overridden UA string is the one sent. CheckUserAgentString(user_agent_override); } -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, UserAgentOverrideIframeRequest) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {accept_ch_ua_iframe_request_url()}); + const std::string user_agent_override = "foo"; SetUserAgentOverride(user_agent_override); - const GURL url = accept_ch_ua_reduced_iframe_request_url(); + const GURL url = accept_ch_ua_iframe_request_url(); // First navigation to set the client hints in the response. ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); - // Second navigation has the Sec-CH-UA-Reduced client hint stored from the - // first navigation's response. + // Second navigation has either Sec-CH-UA-Reduced or Sec-CH-UA-Full client + // hint stored from the first navigation's response. ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), url)); // Since the UA override was set, the UA client hints are *not* added to the // request. - CheckUaReducedClientHint(/*ch_ua_reduced_expected=*/false); + CheckUaOriginTrialClientHint(/*ch_ua_expected=*/false); // Make sure the overridden UA string is the one sent. CheckUserAgentString(user_agent_override); } -IN_PROC_BROWSER_TEST_F(SameOriginUaReducedOriginTrialBrowserTest, - NoAcceptCHRemovesSecChUaReducedFromStorage) { - // The first navigation sets Sec-CH-UA-Reduced in the client hints storage for - // the origin. - NavigateAndCheckHeaders(ua_reduced_with_valid_origin_trial_token_url(), - /*ch_ua_reduced_expected=*/false); - // The second navigation doesn't contain an Accept-CH header in the response, - // so Sec-CH-UA-Reduced is removed from the storage. +IN_PROC_BROWSER_TEST_P(SameOriginUaOriginTrialBrowserTest, + NoAcceptCHRemovesSecChUaFromStorage) { + SetTestOptions( + {/*has_ot_token=*/true, /*valid_ot_token=*/true, + /*has_accept_ch_header=*/true, /*has_critical_ch_header=*/false}, + {ua_with_valid_origin_trial_token_url(), simple_request_url()}); + + // The first navigation sets Sec-CH-UA-Reduced/Sec-CH-UA-Full in the client + // hints storage for the origin. + NavigateAndCheckHeaders(ua_with_valid_origin_trial_token_url(), + /*ch_ua_reduced_expected=*/false, + /*ch_ua_exist_expected=*/false); + // The second navigation doesn't contain an Accept-CH header in the + // response, so Sec-CH-UA-Reduced/Sec-CH-UA-Full is removed from the storage. NavigateAndCheckHeaders(simple_request_url(), - /*ch_ua_reduced_expected=*/true); - // The third navigation doesn't contain a Sec-CH-UA-Reduced in the request - // header because the second navigation caused it to get removed. - NavigateAndCheckHeaders(ua_reduced_with_valid_origin_trial_token_url(), - /*ch_ua_reduced_expected=*/false); + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); + // The third navigation doesn't contain a Sec-CH-UA-Reduced/Sec-CH-UA-Full + // in the request header because the second navigation caused it to get + // removed. + NavigateAndCheckHeaders(ua_with_valid_origin_trial_token_url(), + /*ch_ua_reduced_expected=*/false, + /*ch_ua_exist_expected=*/false); } -// Tests that the Sec-CH-UA-Reduced client hint and the reduced User-Agent -// string are sent on request headers for third-party embedded resources if the -// Origin Trial token from the top-level frame is valid and the permissions -// policy allows it. -class ThirdPartyUaReducedOriginTrialBrowserTest - : public UaReducedOriginTrialBrowserTest { +// Tests that the Sec-CH-UA-Reduced or Sec-CH-UA-Full client hint and the +// reduced User-Agent string are sent on request headers for third-party +// embedded resources if the Origin Trial token from the top-level frame is +// valid and the permissions policy allows it. +class ThirdPartyUaOriginTrialBrowserTest + : public UaOriginTrialBrowserTest, + public testing::WithParamInterface<UserAgentOriginTrialTestType> { public: - ThirdPartyUaReducedOriginTrialBrowserTest() + ThirdPartyUaOriginTrialBrowserTest() : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { https_server_.ServeFilesFromSourceDirectory( "chrome/test/data/client_hints"); https_server_.RegisterRequestMonitor(base::BindRepeating( - &ThirdPartyUaReducedOriginTrialBrowserTest::MonitorResourceRequest, + &ThirdPartyUaOriginTrialBrowserTest::MonitorResourceRequest, base::Unretained(this))); EXPECT_TRUE(https_server_.Start()); } @@ -3655,12 +4005,12 @@ void SetUpOnMainThread() override { InProcessBrowserTest::SetUpOnMainThread(); - // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since - // the origin trial token in the response is associated with a fixed + // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, + // since the origin trial token in the response is associated with a fixed // origin, whereas EmbeddedTestServer serves content on a random port. url_loader_interceptor_ = std::make_unique<URLLoaderInterceptor>(base::BindRepeating( - &ThirdPartyUaReducedOriginTrialBrowserTest::InterceptRequest, + &ThirdPartyUaOriginTrialBrowserTest::InterceptRequest, base::Unretained(this))); } @@ -3669,16 +4019,16 @@ InProcessBrowserTest::TearDownOnMainThread(); } - GURL accept_ch_ua_reduced_cross_origin_iframe_request_url() const { - return GURL(base::StrCat( - {kFirstPartyOriginUrl, - "/accept_ch_ua_reduced_cross_origin_iframe_request.html"})); + GURL accept_ch_ua_cross_origin_iframe_request_url() const { + return GURL( + base::StrCat({kFirstPartyOriginUrl, + "/accept_ch_ua_cross_origin_iframe_request.html"})); } - GURL accept_ch_ua_reduced_cross_origin_subresource_request_url() const { - return GURL(base::StrCat( - {kFirstPartyOriginUrl, - "/accept_ch_ua_reduced_cross_origin_subresource_request.html"})); + GURL accept_ch_ua_cross_origin_subresource_request_url() const { + return GURL( + base::StrCat({kFirstPartyOriginUrl, + "/accept_ch_ua_cross_origin_subresource_request.html"})); } protected: @@ -3687,10 +4037,10 @@ return last_user_agent_; } - const absl::optional<std::string>& GetLastUaReducedClientHintValue() + const absl::optional<std::string>& GetLastUaOriginTrialClientHintValue() override { base::AutoLock lock(last_request_lock_); - return last_sec_ch_ua_reduced_; + return last_sec_ch_ua_value_; } const absl::optional<GURL>& GetLastRequestedURL() { @@ -3698,8 +4048,8 @@ return last_requested_url_; } - void SetUaReducedPermissionsPolicy(const std::string& value) { - ua_reduced_permissions_policy_header_value_ = value; + void SetUaPermissionsPolicy(const std::string& value) { + ua_permissions_policy_header_value_ = value; } void SetValidOTToken(const bool valid_ot_token) { @@ -3716,9 +4066,10 @@ return false; } if (params->url_request.url.path() != - "/accept_ch_ua_reduced_cross_origin_iframe_request.html" && + base::StrCat({"/accept_ch_ua_cross_origin_iframe_request.html"}) && params->url_request.url.path() != - "/accept_ch_ua_reduced_cross_origin_subresource_request.html") { + base::StrCat( + {"/accept_ch_ua_cross_origin_subresource_request.html"})) { return false; } @@ -3728,32 +4079,59 @@ // // The Origin Trial token expires in 2033. Generate a new token by then, or // find a better way to re-generate a test trial token. - static constexpr const char kOriginTrialToken[] = + static constexpr const char kOriginTrialTokenReduced[] = "AziP2Iyo74PHkJAVVXJ1NBAyZd+" "GZFmTqpFtug4Wazsj5rQPFeCFjjZpiEYb086vZzi48lF1ydynMj/" "oLqqLXgEAAABeeyJvcmlnaW4iOiAiaHR0cHM6Ly9teS1zaXRlLmNvbTo0NDQ0NCIsICJmZ" "WF0dXJlIjogIlVzZXJBZ2VudFJlZHVjdGlvbiIsICJleHBpcnkiOiAyMDAwMDAwMDAwfQ=" "="; + // Generated by running (in tools/origin_trials): + // generate_token.py https://my-site.com:44444 + // SendFullUserAgentAfterReduction --expire-timestamp=2000000000 + // + // The Origin Trial token expires in 2033. Generate a new token by then, + // or find a better way to re-generate a test trial token. + static constexpr const char kOriginTrialTokenFull[] = + "A/qRZSBJ/" + "wuh1vOPO1X3x79VvjXlKiWldDIX0ra1iQf2FBB7yHPCQ3rEEHOc8S0cnWUG8as1k98sUyV" + "xGawmmggAAABreyJvcmlnaW4iOiAiaHR0cHM6Ly9teS1zaXRlLmNvbTo0NDQ0NCIsICJmZ" + "WF0dXJlIjogIlNlbmRGdWxsVXNlckFnZW50QWZ0ZXJSZWR1Y3Rpb24iLCAiZXhwaXJ5Ijo" + "gMjAwMDAwMDAwMH0="; + // Construct and send the response. std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/html; charset=utf-8\n"; - base::StrAppend(&headers, {"Accept-CH: Sec-CH-UA-Reduced\n"}); base::StrAppend(&headers, - {"Permissions-Policy: ch-ua-reduced=", - ua_reduced_permissions_policy_header_value_, "\n"}); - base::StrAppend(&headers, {"Origin-Trial: ", - valid_ot_token_ ? kOriginTrialToken - : "invalid-origin-trial-token", - "\n\n"}); + {"Accept-CH: ", + GetParam() == UserAgentOriginTrialTestType::UAReduction + ? "Sec-CH-UA-Reduced" + : "Sec-CH-UA-Full", + "\n"}); + base::StrAppend(&headers, + {"Permissions-Policy: ", + GetParam() == UserAgentOriginTrialTestType::UAReduction + ? "ch-ua-reduced=" + : "ch-ua-full=", + ua_permissions_policy_header_value_, "\n"}); + + base::StrAppend( + &headers, + {"Origin-Trial: ", + valid_ot_token_ + ? (GetParam() == UserAgentOriginTrialTestType::UAReduction + ? kOriginTrialTokenReduced + : kOriginTrialTokenFull) + : "invalid-origin-trial-token", + "\n\n"}); std::string body = "<html><head>"; if (params->url_request.url.path() == - "/accept_ch_ua_reduced_cross_origin_subresource_request.html") { + base::StrCat({"/accept_ch_ua_cross_origin_subresource_request.html"})) { base::StrAppend(&body, {BuildSubresourceHTML()}); } base::StrAppend(&body, {"</head><body>"}); if (params->url_request.url.path() == - "/accept_ch_ua_reduced_cross_origin_iframe_request.html") { + base::StrCat({"/accept_ch_ua_cross_origin_iframe_request.html"})) { base::StrAppend(&body, {BuildIframeHTML()}); } base::StrAppend(&body, {"</body></html>"}); @@ -3770,12 +4148,12 @@ } } - void SetLastSecChUaReduced(const std::string* value) { + void SetLastSecChUaValue(const std::string* value) { base::AutoLock lock(last_request_lock_); if (value != nullptr) { - last_sec_ch_ua_reduced_ = *value; + last_sec_ch_ua_value_ = *value; } else { - last_sec_ch_ua_reduced_ = absl::nullopt; + last_sec_ch_ua_value_ = absl::nullopt; } } @@ -3789,8 +4167,11 @@ SetLastRequestedURL(request.GetURL()); auto it = request.headers.find("user-agent"); SetLastUserAgent(it != request.headers.end() ? &it->second : nullptr); - it = request.headers.find("sec-ch-ua-reduced"); - SetLastSecChUaReduced(it != request.headers.end() ? &it->second : nullptr); + it = request.headers.find( + base::StrCat({GetParam() == UserAgentOriginTrialTestType::UAReduction + ? "sec-ch-ua-reduced" + : "sec-ch-ua-full"})); + SetLastSecChUaValue(it != request.headers.end() ? &it->second : nullptr); } std::string BuildIframeHTML() { @@ -3809,115 +4190,138 @@ std::unique_ptr<URLLoaderInterceptor> url_loader_interceptor_; net::EmbeddedTestServer https_server_; - std::string ua_reduced_permissions_policy_header_value_; + std::string ua_permissions_policy_header_value_; bool valid_ot_token_ = true; base::Lock last_request_lock_; absl::optional<std::string> last_user_agent_ GUARDED_BY(last_request_lock_); - absl::optional<std::string> last_sec_ch_ua_reduced_ + absl::optional<std::string> last_sec_ch_ua_value_ GUARDED_BY(last_request_lock_); absl::optional<GURL> last_requested_url_ GUARDED_BY(last_request_lock_); }; -constexpr const char - ThirdPartyUaReducedOriginTrialBrowserTest::kFirstPartyOriginUrl[]; +INSTANTIATE_TEST_SUITE_P( + All, + ThirdPartyUaOriginTrialBrowserTest, + testing::Values(UserAgentOriginTrialTestType::UAReduction, + UserAgentOriginTrialTestType::UADeprecation, + UserAgentOriginTrialTestType::UAReductionAndDeprecation)); -IN_PROC_BROWSER_TEST_F(ThirdPartyUaReducedOriginTrialBrowserTest, - ThirdPartyIframeUaReducedWildcardPolicy) { - SetUaReducedPermissionsPolicy("*"); // Allow all third-party sites. +constexpr const char ThirdPartyUaOriginTrialBrowserTest::kFirstPartyOriginUrl[]; - NavigateAndCheckHeaders( - accept_ch_ua_reduced_cross_origin_iframe_request_url(), - /*ch_ua_reduced_expected=*/true); +IN_PROC_BROWSER_TEST_P(ThirdPartyUaOriginTrialBrowserTest, + ThirdPartyIframeUaWildcardPolicy) { + SetUaPermissionsPolicy("*"); // Allow all third-party sites. - // Make sure the last intercepted URL was the request for the embedded iframe. + NavigateAndCheckHeaders(accept_ch_ua_cross_origin_iframe_request_url(), + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); + + // Make sure the last intercepted URL was the request for the embedded + // iframe. EXPECT_EQ(GetLastRequestedURL()->path(), "/simple.html"); } -IN_PROC_BROWSER_TEST_F(ThirdPartyUaReducedOriginTrialBrowserTest, - ThirdPartySubresourceUaReducedWithWildcardPolicy) { - SetUaReducedPermissionsPolicy("*"); // Allow all third-party sites. +IN_PROC_BROWSER_TEST_P(ThirdPartyUaOriginTrialBrowserTest, + ThirdPartySubresourceUaWithWildcardPolicy) { + SetUaPermissionsPolicy("*"); // Allow all third-party sites. - NavigateAndCheckHeaders( - accept_ch_ua_reduced_cross_origin_subresource_request_url(), - /*ch_ua_reduced_expected=*/true); + NavigateAndCheckHeaders(accept_ch_ua_cross_origin_subresource_request_url(), + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); - // Make sure the last intercepted URL was the request for the embedded iframe. + // Make sure the last intercepted URL was the request for the embedded + // iframe. EXPECT_EQ(GetLastRequestedURL()->path(), "/style.css"); } -IN_PROC_BROWSER_TEST_F(ThirdPartyUaReducedOriginTrialBrowserTest, - ThirdPartyIframeUaReducedSpecificPolicy) { +IN_PROC_BROWSER_TEST_P(ThirdPartyUaOriginTrialBrowserTest, + ThirdPartyIframeUaSpecificPolicy) { std::string policy = "(self \""; base::StrAppend(&policy, {GetServerOrigin().spec(), "\")"}); - SetUaReducedPermissionsPolicy(policy); // Allow our third-party site only. + SetUaPermissionsPolicy(policy); // Allow our third-party site only. - NavigateAndCheckHeaders( - accept_ch_ua_reduced_cross_origin_iframe_request_url(), - /*ch_ua_reduced_expected=*/true); + NavigateAndCheckHeaders(accept_ch_ua_cross_origin_iframe_request_url(), + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); - // Make sure the last intercepted URL was the request for the embedded iframe. + // Make sure the last intercepted URL was the request for the embedded + // iframe. EXPECT_EQ(GetLastRequestedURL()->path(), "/simple.html"); } -IN_PROC_BROWSER_TEST_F(ThirdPartyUaReducedOriginTrialBrowserTest, - ThirdPartySubresourceUaReducedSpecificPolicy) { +IN_PROC_BROWSER_TEST_P(ThirdPartyUaOriginTrialBrowserTest, + ThirdPartySubresourceUaSpecificPolicy) { std::string policy = "(self \""; base::StrAppend(&policy, {GetServerOrigin().spec(), "\")"}); - SetUaReducedPermissionsPolicy(policy); // Allow our third-party site only. + SetUaPermissionsPolicy(policy); // Allow our third-party site only. - NavigateAndCheckHeaders( - accept_ch_ua_reduced_cross_origin_subresource_request_url(), - /*ch_ua_reduced_expected=*/true); + NavigateAndCheckHeaders(accept_ch_ua_cross_origin_subresource_request_url(), + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); - // Make sure the last intercepted URL was the request for the embedded iframe. + // Make sure the last intercepted URL was the request for the embedded + // iframe. EXPECT_EQ(GetLastRequestedURL()->path(), "/style.css"); } -IN_PROC_BROWSER_TEST_F(ThirdPartyUaReducedOriginTrialBrowserTest, - ThirdPartyIframeUaReducedInvalidOriginTrialToken) { - SetUaReducedPermissionsPolicy("*"); // Allow all third-party sites. - SetValidOTToken(false); // Origin Trial Token is invalid. +IN_PROC_BROWSER_TEST_P(ThirdPartyUaOriginTrialBrowserTest, + ThirdPartyIframeUaInvalidOriginTrialToken) { + SetUaPermissionsPolicy("*"); // Allow all third-party sites. + SetValidOTToken(false); // Origin Trial Token is invalid. - NavigateAndCheckHeaders( - accept_ch_ua_reduced_cross_origin_iframe_request_url(), - /*ch_ua_reduced_expected=*/false); + NavigateAndCheckHeaders(accept_ch_ua_cross_origin_iframe_request_url(), + /*ch_ua_reduced_expected=*/false, + /*ch_ua_exist_expected=*/false); - // Make sure the last intercepted URL was the request for the embedded iframe. + // Make sure the last intercepted URL was the request for the embedded + // iframe. EXPECT_EQ(GetLastRequestedURL()->path(), "/simple.html"); } -IN_PROC_BROWSER_TEST_F(ThirdPartyUaReducedOriginTrialBrowserTest, - ThirdPartySubresourceUaReducedInvalidOriginTrialToken) { - SetUaReducedPermissionsPolicy("*"); // Allow all third-party sites. - SetValidOTToken(false); // Origin Trial Token is invalid. +IN_PROC_BROWSER_TEST_P(ThirdPartyUaOriginTrialBrowserTest, + ThirdPartySubresourceUaInvalidOriginTrialToken) { + SetUaPermissionsPolicy("*"); // Allow all third-party sites. + SetValidOTToken(false); // Origin Trial Token is invalid. - NavigateAndCheckHeaders( - accept_ch_ua_reduced_cross_origin_subresource_request_url(), - /*ch_ua_reduced_expected=*/false); + NavigateAndCheckHeaders(accept_ch_ua_cross_origin_subresource_request_url(), + /*ch_ua_reduced_expected=*/false, + /*ch_ua_exist_expected=*/false); - // Make sure the last intercepted URL was the request for the embedded iframe. + // Make sure the last intercepted URL was the request for the embedded + // iframe. EXPECT_EQ(GetLastRequestedURL()->path(), "/style.css"); } // A test fixture for setting Accept-CH and Origin-Trial response headers for // third-party embeds. This suite of tests ensures that third-party embeds -// with Sec-CH-UA-Reduced and a valid Origin Trial token send a reduced UA -// string in the User-Agent header, even if the top-level page is not enrolled -// in the UA reduction origin trial. +// with Sec-CH-UA-Reduced or Sec-CH-UA-Full and a valid Origin Trial token send +// the reduced UA string if Sec-CH-UA-Reduced set, or the full UA string if +// Sec-CH-UA-Full set in the request header, even if the top-level page is +// not enrolled in the UA reduction origin trial. // -// The Origin Trial token in the header files were generated by running (in -// tools/origin_trials): -// generate_token.py https://my-site.com:44444 UserAgentReduction +// The Origin Trial token for UserAgentReduction in the header files were +// generated by running (in tools/origin_trials): generate_token.py +// https://my-site.com:44444 UserAgentReduction // --is-third-party --expire-timestamp=2000000000 -class ThirdPartyAcceptChUaReducedOriginTrialBrowserTest - : public UaReducedOriginTrialBrowserTest { +// +// The Origin Trial token for SendFullUserAgentAfterReduction in the header +// files were generated by running (in tools/origin_trials): generate_token.py +// https://my-site.com:44444 SendFullUserAgentAfterReduction +// --is-third-party --expire-timestamp=2000000000 +class ThirdPartyAcceptChUaOriginTrialBrowserTest + : public UaOriginTrialBrowserTest, + public testing::WithParamInterface<UserAgentOriginTrialTestType> { public: - ThirdPartyAcceptChUaReducedOriginTrialBrowserTest() + ThirdPartyAcceptChUaOriginTrialBrowserTest() : https_server_(net::EmbeddedTestServer::TYPE_HTTPS) { https_server_.ServeFilesFromSourceDirectory( "chrome/test/data/client_hints"); https_server_.RegisterRequestMonitor(base::BindRepeating( - &ThirdPartyAcceptChUaReducedOriginTrialBrowserTest::MonitorRequest, + &ThirdPartyAcceptChUaOriginTrialBrowserTest::MonitorRequest, base::Unretained(this))); EXPECT_TRUE(https_server_.Start()); } @@ -3932,10 +4336,10 @@ // the third-party requests, since the origin trial token in the response // is associated with a fixed origin, whereas EmbeddedTestServer serves // content on a random port. - url_loader_interceptor_ = std::make_unique< - URLLoaderInterceptor>(base::BindRepeating( - &ThirdPartyAcceptChUaReducedOriginTrialBrowserTest::InterceptRequest, - base::Unretained(this))); + url_loader_interceptor_ = + std::make_unique<URLLoaderInterceptor>(base::BindRepeating( + &ThirdPartyAcceptChUaOriginTrialBrowserTest::InterceptRequest, + base::Unretained(this))); } void TearDownOnMainThread() override { @@ -3943,18 +4347,19 @@ InProcessBrowserTest::TearDownOnMainThread(); } - GURL accept_ch_ua_reduced_cross_origin_iframe_request_url() const { - return https_server_.GetURL( - "/accept_ch_ua_reduced_cross_origin_iframe_with_ot_request.html"); + GURL accept_ch_ua_cross_origin_iframe_request_url() const { + return https_server_.GetURL(base::StrCat( + {"/accept_ch_ua_cross_origin_iframe_with_ot_request.html"})); } - GURL accept_ch_ua_reduced_cross_origin_iframe_with_subrequests_url() const { - return https_server_.GetURL( - "/accept_ch_ua_reduced_cross_origin_iframe_with_subrequests.html"); + GURL accept_ch_ua_cross_origin_iframe_with_subrequests_url() const { + return https_server_.GetURL(base::StrCat( + {"/accept_ch_ua_cross_origin_iframe_with_subrequests.html"})); } GURL top_level_with_iframe_redirect_url() const { - return https_server_.GetURL("/top_level_with_iframe_redirect.html"); + return https_server_.GetURL( + base::StrCat({"/top_level_with_iframe_redirect.html"})); } protected: @@ -3963,10 +4368,10 @@ return last_user_agent_; } - const absl::optional<std::string>& GetLastUaReducedClientHintValue() + const absl::optional<std::string>& GetLastUaOriginTrialClientHintValue() override { base::AutoLock lock(last_request_lock_); - return last_sec_ch_ua_reduced_; + return last_sec_ch_ua_vaule_; } const absl::optional<GURL>& GetLastRequestedURL() { @@ -3987,29 +4392,105 @@ return false; } + // Filter out unknown paths to avoid flaky tests. + static constexpr auto kExpectedPaths = + base::MakeFixedFlatSet<base::StringPiece>({ + "/basic.html", + "/frame_3p_ot.html", + "/nested_style.css", + "/redirect_style.css", + "/simple_3p_ot.html", + "/style.css", + "/subresource_redirect.html", + }); + const std::string path = params->url_request.url.path(); + if (!base::Contains(kExpectedPaths, path)) { + return false; + } + SetLastRequestedURL(params->url_request.url); std::string user_agent; params->url_request.headers.GetHeader("user-agent", &user_agent); SetLastUserAgent(&user_agent); - std::string sec_ch_ua_reduced; - params->url_request.headers.GetHeader("sec-ch-ua-reduced", - &sec_ch_ua_reduced); - SetLastSecChUaReduced(&sec_ch_ua_reduced); + std::string sec_ch_ua_value; + params->url_request.headers.GetHeader( + base::StrCat({GetParam() == UserAgentOriginTrialTestType::UAReduction + ? "sec-ch-ua-reduced" + : "sec-ch-ua-full"}), + &sec_ch_ua_value); + SetLastSecChUaValue(&sec_ch_ua_value); - const std::string path = params->url_request.url.path(); if (path == "/style.css" || path == "/basic.html" || path == "/nested_style.css") { // These paths are known to be the last request (with no subrequest // after them), so verify that the UA string is set appropriately. - const bool ch_ua_reduced_expected = true; - CheckUaReducedClientHint(ch_ua_reduced_expected); + const bool ch_ua_reduced_expected = + GetParam() == UserAgentOriginTrialTestType::UAReduction; + const bool ch_ua_exist_expected = true; + CheckUaOriginTrialClientHint(ch_ua_exist_expected); CheckUserAgentReduced(ch_ua_reduced_expected); } std::string resource_path = "chrome/test/data/client_hints"; - resource_path.append(std::string(params->url_request.url.path_piece())); + resource_path.append( + static_cast<std::string>(params->url_request.url.path_piece())); - URLLoaderInterceptor::WriteResponse(resource_path, params->client.get()); + // Only build mock header with origin trial tokens for the third party + // requests. + if (origin != GURL(kThirdPartyOriginUrl)) { + URLLoaderInterceptor::WriteResponse(resource_path, params->client.get()); + return true; + } + + // Generated by running (in tools/origin_trials): + // generate_token.py https://my-site.com:44444 UserAgentReduction + // --is-third-party --expire-timestamp=2000000000 + // + // The Origin Trial token expires in 2033. Generate a new token by then, or + // find a better way to re-generate a test trial token. + static constexpr const char kOriginTrialTokenReduced[] = + "Awgc/" + "axBbE+4mDB+z2AKFEl26TUKBzCM2GBkDQmt4IephJgHpel1kcsIdCCBYKUgJ4s4+" + "JQLXFKkOCs7lFIISAMAAAB0eyJvcmlnaW4iOiAiaHR0cHM6Ly9teS1zaXRlLmNvbTo0NDQ" + "0NCIsICJpc1RoaXJkUGFydHkiOiB0cnVlLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y" + "3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0="; + + // Generated by running (in tools/origin_trials): + // generate_token.py https://my-site.com:44444 + // SendFullUserAgentAfterReduction --is-third-party + // --expire-timestamp=2000000000 + // + // The Origin Trial token expires in 2033. Generate a new token by then, + // or find a better way to re-generate a test trial token. + static constexpr const char kOriginTrialTokenFull[] = + "AznwSelRzlbEO7T3NXT68fp+" + "k7amzJdYhxfcUEH3M7WTMES73QlwoqK8zBNVd1rGDvFuDxDbDILL4pr7Og6wJw0AAACBey" + "JvcmlnaW4iOiAiaHR0cHM6Ly9teS1zaXRlLmNvbTo0NDQ0NCIsICJpc1RoaXJkUGFydHki" + "OiB0cnVlLCAiZmVhdHVyZSI6ICJTZW5kRnVsbFVzZXJBZ2VudEFmdGVyUmVkdWN0aW9uIi" + "wgImV4cGlyeSI6IDIwMDAwMDAwMDB9"; + + std::string headers = "HTTP/1.1 200 OK\nContent-Type: text/html\n"; + switch (GetParam()) { + case UserAgentOriginTrialTestType::UAReduction: + base::StrAppend(&headers, {"Accept-CH: ", "Sec-CH-UA-Reduced", "\n"}); + base::StrAppend(&headers, {"Origin-Trial: ", kOriginTrialTokenReduced}); + break; + case UserAgentOriginTrialTestType::UADeprecation: + base::StrAppend(&headers, {"Accept-CH: ", "Sec-CH-UA-Full", "\n"}); + base::StrAppend(&headers, {"Origin-Trial: ", kOriginTrialTokenFull}); + break; + case UserAgentOriginTrialTestType::UAReductionAndDeprecation: + base::StrAppend( + &headers, + {"Accept-CH: ", "Sec-CH-UA-Reduced, Sec-CH-UA-Full", "\n"}); + base::StrAppend(&headers, {"Origin-Trial: ", kOriginTrialTokenReduced, + ",", kOriginTrialTokenFull}); + break; + default: + break; + } + URLLoaderInterceptor::WriteResponse(resource_path, params->client.get(), + &headers); return true; } @@ -4019,8 +4500,12 @@ // one, since they don't respond with a valid Origin Trial token. CheckUserAgentMinorVersion(request.headers.at("user-agent"), /*expected_user_agent_reduced=*/false); - request.headers.find("sec-ch-ua-reduced"); - EXPECT_THAT(request.headers, Not(Contains(Key("sec-ch-ua-reduced")))); + std::string sec_ua_ch_name = + base::StrCat({GetParam() == UserAgentOriginTrialTestType::UAReduction + ? "sec-ch-ua-reduced" + : "sec-ch-ua-full"}); + request.headers.find(sec_ua_ch_name); + EXPECT_THAT(request.headers, Not(Contains(Key(sec_ua_ch_name)))); } void SetLastUserAgent(const std::string* value) { @@ -4032,12 +4517,12 @@ } } - void SetLastSecChUaReduced(const std::string* value) { + void SetLastSecChUaValue(const std::string* value) { base::AutoLock lock(last_request_lock_); if (value != nullptr && !value->empty()) { - last_sec_ch_ua_reduced_ = *value; + last_sec_ch_ua_vaule_ = *value; } else { - last_sec_ch_ua_reduced_ = absl::nullopt; + last_sec_ch_ua_vaule_ = absl::nullopt; } } @@ -4050,46 +4535,43 @@ net::EmbeddedTestServer https_server_; base::Lock last_request_lock_; absl::optional<std::string> last_user_agent_ GUARDED_BY(last_request_lock_); - absl::optional<std::string> last_sec_ch_ua_reduced_ + absl::optional<std::string> last_sec_ch_ua_vaule_ GUARDED_BY(last_request_lock_); absl::optional<GURL> last_requested_url_ GUARDED_BY(last_request_lock_); }; -constexpr char - ThirdPartyAcceptChUaReducedOriginTrialBrowserTest::kThirdPartyOriginUrl[]; +INSTANTIATE_TEST_SUITE_P( + All, + ThirdPartyAcceptChUaOriginTrialBrowserTest, + testing::Values(UserAgentOriginTrialTestType::UAReduction, + UserAgentOriginTrialTestType::UADeprecation, + UserAgentOriginTrialTestType::UAReductionAndDeprecation)); -// Flaky with ASAN. crbug.com/1293876 -#if defined(ADDRESS_SANITIZER) -#define MAYBE_ThirdPartyIframeUaReducedWithOriginTrialToken \ - DISABLED_ThirdPartyIframeUaReducedWithOriginTrialToken -#else -#define MAYBE_ThirdPartyIframeUaReducedWithOriginTrialToken \ - ThirdPartyIframeUaReducedWithOriginTrialToken -#endif -IN_PROC_BROWSER_TEST_F(ThirdPartyAcceptChUaReducedOriginTrialBrowserTest, - MAYBE_ThirdPartyIframeUaReducedWithOriginTrialToken) { +constexpr char + ThirdPartyAcceptChUaOriginTrialBrowserTest::kThirdPartyOriginUrl[]; + +IN_PROC_BROWSER_TEST_P(ThirdPartyAcceptChUaOriginTrialBrowserTest, + ThirdPartyIframeUaWithOriginTrialToken) { const GURL top_level_frame_url = - accept_ch_ua_reduced_cross_origin_iframe_request_url(); + accept_ch_ua_cross_origin_iframe_request_url(); // The first navigation is to opt-into the OT. NavigateAndCheckHeaders(top_level_frame_url, - /*ch_ua_reduced_expected=*/false); - NavigateAndCheckHeaders(top_level_frame_url, /*ch_ua_reduced_expected=*/true); - // Make sure the last intercepted URL was the request for the embedded iframe. - EXPECT_EQ(GetLastRequestedURL()->path(), "/simple_3p_ot.html"); + /*ch_ua_reduced_expected=*/false, + /*ch_ua_exist_expected=*/false); + NavigateAndCheckHeaders(top_level_frame_url, + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); + // Make sure the last intercepted URL was the request for the embedded + // iframe. + EXPECT_EQ(GetLastRequestedURL()->path(), + base::StrCat({"/simple_3p_ot.html"})); } -// Flaky with ASAN. crbug.com/1293876 -#if defined(ADDRESS_SANITIZER) -#define MAYBE_ThirdPartyIframeUaReducedWithAllCookiesBlocked \ - DISABLED_ThirdPartyIframeUaReducedWithAllCookiesBlocked -#else -#define MAYBE_ThirdPartyIframeUaReducedWithAllCookiesBlocked \ - ThirdPartyIframeUaReducedWithAllCookiesBlocked -#endif -IN_PROC_BROWSER_TEST_F(ThirdPartyAcceptChUaReducedOriginTrialBrowserTest, - MAYBE_ThirdPartyIframeUaReducedWithAllCookiesBlocked) { +IN_PROC_BROWSER_TEST_P(ThirdPartyAcceptChUaOriginTrialBrowserTest, + ThirdPartyIframeUaWithAllCookiesBlocked) { const GURL top_level_frame_url = - accept_ch_ua_reduced_cross_origin_iframe_request_url(); + accept_ch_ua_cross_origin_iframe_request_url(); const GURL third_party_iframe_url = GURL(kThirdPartyOriginUrl); // Block all cookies for the third-party origin. @@ -4102,24 +4584,19 @@ // embed, which shouldn't happen for this test because third-party cookies // are blocked. NavigateAndCheckHeaders(top_level_frame_url, - /*ch_ua_reduced_expected=*/false); + /*ch_ua_reduced_expected=*/false, + /*ch_ua_exist_expected=*/false); NavigateAndCheckHeaders(top_level_frame_url, - /*ch_ua_reduced_expected=*/false); - // Make sure the last intercepted URL was the request for the embedded iframe. - EXPECT_EQ(GetLastRequestedURL()->path(), "/simple_3p_ot.html"); + /*ch_ua_reduced_expected=*/false, + /*ch_ua_exist_expected=*/false); + // Make sure the last intercepted URL was the request for the embedded + // iframe. + EXPECT_EQ(GetLastRequestedURL()->path(), + base::StrCat({"/simple_3p_ot.html"})); } -// Flaky with ASAN. crbug.com/1293876 -#if defined(ADDRESS_SANITIZER) -#define MAYBE_ThirdPartyIframeUaReducedWithThirdPartyCookiesBlocked \ - DISABLED_ThirdPartyIframeUaReducedWithThirdPartyCookiesBlocked -#else -#define MAYBE_ThirdPartyIframeUaReducedWithThirdPartyCookiesBlocked \ - ThirdPartyIframeUaReducedWithThirdPartyCookiesBlocked -#endif -IN_PROC_BROWSER_TEST_F( - ThirdPartyAcceptChUaReducedOriginTrialBrowserTest, - MAYBE_ThirdPartyIframeUaReducedWithThirdPartyCookiesBlocked) { +IN_PROC_BROWSER_TEST_P(ThirdPartyAcceptChUaOriginTrialBrowserTest, + ThirdPartyIframeUaWithThirdPartyCookiesBlocked) { // Block third-party cookies. browser()->profile()->GetPrefs()->SetInteger( prefs::kCookieControlsMode, @@ -4127,48 +4604,48 @@ // The first navigation is to attempt to opt-into the OT for the third-party // embed, which shouldn't happen for this test because cookies are blocked. - NavigateAndCheckHeaders( - accept_ch_ua_reduced_cross_origin_iframe_request_url(), - /*ch_ua_reduced_expected=*/false); - NavigateAndCheckHeaders( - accept_ch_ua_reduced_cross_origin_iframe_request_url(), - /*ch_ua_reduced_expected=*/false); - // Make sure the last intercepted URL was the request for the embedded iframe. - EXPECT_EQ(GetLastRequestedURL()->path(), "/simple_3p_ot.html"); + NavigateAndCheckHeaders(accept_ch_ua_cross_origin_iframe_request_url(), + /*ch_ua_reduced_expected=*/false, + /*ch_ua_exist_expected=*/false); + NavigateAndCheckHeaders(accept_ch_ua_cross_origin_iframe_request_url(), + /*ch_ua_reduced_expected=*/false, + /*ch_ua_exist_expected=*/false); + // Make sure the last intercepted URL was the request for the embedded + // iframe. + EXPECT_EQ(GetLastRequestedURL()->path(), + base::StrCat({"/simple_3p_ot.html"})); } -IN_PROC_BROWSER_TEST_F( - ThirdPartyAcceptChUaReducedOriginTrialBrowserTest, - DISABLED_ThirdPartyIframeUaReducedWithSubresourceRequests) { +IN_PROC_BROWSER_TEST_P(ThirdPartyAcceptChUaOriginTrialBrowserTest, + ThirdPartyIframeUaWithSubresourceRequests) { // The first navigation is to opt-into the OT. Since there are subresource // requests, the last processed requests from the first navigation will have - // the reduced UA string. + // the corresponding reduced or full UA string. NavigateAndCheckHeaders( - accept_ch_ua_reduced_cross_origin_iframe_with_subrequests_url(), - /*ch_ua_reduced_expected=*/true); + accept_ch_ua_cross_origin_iframe_with_subrequests_url(), + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); NavigateAndCheckHeaders( - accept_ch_ua_reduced_cross_origin_iframe_with_subrequests_url(), - /*ch_ua_reduced_expected=*/true); + accept_ch_ua_cross_origin_iframe_with_subrequests_url(), + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); } -// Flaky with ASAN. crbug.com/1293876 -#if defined(ADDRESS_SANITIZER) -#define MAYBE_ThirdPartyIframeUaReducedWithSubresourceRedirectRequests \ - DISABLED_ThirdPartyIframeUaReducedWithSubresourceRedirectRequests -#else -#define MAYBE_ThirdPartyIframeUaReducedWithSubresourceRedirectRequests \ - ThirdPartyIframeUaReducedWithSubresourceRedirectRequests -#endif -IN_PROC_BROWSER_TEST_F( - ThirdPartyAcceptChUaReducedOriginTrialBrowserTest, - MAYBE_ThirdPartyIframeUaReducedWithSubresourceRedirectRequests) { +IN_PROC_BROWSER_TEST_P(ThirdPartyAcceptChUaOriginTrialBrowserTest, + ThirdPartyIframeUaWithSubresourceRedirectRequests) { // The first navigation is to opt-into the OT. Since there are subresource // requests, the last processed requests from the first navigation will have - // the reduced UA string. + // the corresponding reduced or full UA string. NavigateAndCheckHeaders(top_level_with_iframe_redirect_url(), - /*ch_ua_reduced_expected=*/true); + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); NavigateAndCheckHeaders(top_level_with_iframe_redirect_url(), - /*ch_ua_reduced_expected=*/true); + /*ch_ua_reduced_expected=*/GetParam() == + UserAgentOriginTrialTestType::UAReduction, + /*ch_ua_exist_expected=*/true); } // CrOS multi-profiles implementation is too different for these tests. @@ -4343,8 +4820,8 @@ GreaseEnterprisePolicyDynamicRefreshTest) { const GURL gurl = accept_ch_url(); // Reset the policy that was already set to false in the setup, then see if - // the change is reflected in the sec-ch-ua header without requiring a browser - // restart. + // the change is reflected in the sec-ch-ua header without requiring a + // browser restart. policy::PolicyMap policies; SetPolicy(&policies, policy::key::kUserAgentClientHintsGREASEUpdateEnabled, absl::optional<base::Value>(true)); @@ -4388,8 +4865,8 @@ } void SetUpOnMainThread() override { - // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, since - // the origin trial token in the response is associated with a fixed + // We use a URLLoaderInterceptor, rather than the EmbeddedTestServer, + // since the origin trial token in the response is associated with a fixed // origin, whereas EmbeddedTestServer serves content on a random port. url_loader_interceptor_ = std::make_unique<URLLoaderInterceptor>(base::BindRepeating( @@ -4424,7 +4901,8 @@ } std::string resource_path = "chrome/test/data/client_hints"; - resource_path.append(std::string(params->url_request.url.path_piece())); + resource_path.append( + static_cast<std::string>(params->url_request.url.path_piece())); URLLoaderInterceptor::WriteResponse(resource_path, params->client.get()); return true; }
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java index 29e8b08b..d7900414 100644 --- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java +++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManager.java
@@ -504,6 +504,22 @@ } /** + * Check if the shown notifications in given window have reached the max allowed number. + */ + boolean hasReachedMaxAllowedNotificationNumber(@SystemNotificationType int type) { + boolean hasReached = updateNotificationTimestamps(type, false) + >= PriceTrackingNotificationConfig.getMaxAllowedNotificationNumber(type); + String managementType = notificationTypeToManagementType(type); + if (managementType != null) { + RecordHistogram.recordBooleanHistogram( + String.format(Locale.US, "Commerce.PriceDrops.%s.NotificationReachedCap", + managementType), + hasReached); + } + return hasReached; + } + + /** * Update the stored notification timestamps. Outdated timestamps are removed and current * timestamp could be attached. * @@ -556,6 +572,17 @@ } } + private String notificationTypeToManagementType(@SystemNotificationType int type) { + if (type == SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED) { + return "ChromeManaged"; + } else if (type == SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED) { + return "UserManaged"; + } else { + Log.e(TAG, "Invalid notification type."); + return null; + } + } + private static void dismissNotification(int notificationId) { new NotificationManagerProxyImpl(ContextUtils.getApplicationContext()) .cancel(PriceDropNotifier.NOTIFICATION_TAG, notificationId);
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifier.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifier.java index 84f2fe6..b65dc3a 100644 --- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifier.java +++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifier.java
@@ -14,6 +14,7 @@ import androidx.annotation.VisibleForTesting; import org.chromium.base.Callback; +import org.chromium.base.Log; import org.chromium.chrome.R; import org.chromium.chrome.browser.notifications.NotificationUmaTracker; import org.chromium.chrome.browser.notifications.NotificationUmaTracker.ActionType; @@ -38,6 +39,7 @@ * ImageFetcher} without cache. */ public class PriceDropNotifier { + private static final String TAG = "PriceTrackNotif"; public static final String NOTIFICATION_TAG = "price_drop"; static class NotificationData { @@ -97,7 +99,7 @@ private final Context mContext; private ImageFetcher mImageFetcher; private final NotificationManagerProxy mNotificationManagerProxy; - private final PriceDropNotificationManager mPriceDropNotificationManager; + private PriceDropNotificationManager mPriceDropNotificationManager; /** * Creates a {@link PriceDropNotifier} instance. @@ -156,6 +158,13 @@ int notificationId = getNotificationId(notificationData.offerId); @SystemNotificationType int notificationType = getUmaNotificationType(notificationData); + if (mPriceDropNotificationManager.hasReachedMaxAllowedNotificationNumber( + notificationType)) { + Log.e(TAG, + "Unable to show this notification" + + " because we have reached the max allowed number."); + return; + } NotificationWrapperBuilder notificationBuilder = getNotificationBuilder(notificationType, notificationId); if (icon != null) { @@ -222,4 +231,9 @@ ? SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED : SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED; } + + @VisibleForTesting + void setPriceDropNotificationManagerForTesting(PriceDropNotificationManager manager) { + mPriceDropNotificationManager = manager; + } }
diff --git a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationConfig.java b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationConfig.java index 63197098..3458478b 100644 --- a/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationConfig.java +++ b/chrome/browser/commerce/price_tracking/android/java/src/org/chromium/chrome/browser/price_tracking/PriceTrackingNotificationConfig.java
@@ -5,15 +5,22 @@ package org.chromium.chrome.browser.price_tracking; import org.chromium.base.FeatureList; +import org.chromium.base.Log; import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.notifications.NotificationUmaTracker.SystemNotificationType; import java.util.concurrent.TimeUnit; /** Flag configuration for Price Tracking Notification experience. */ public class PriceTrackingNotificationConfig { + private static final String TAG = "PriceTrackNotif"; private static final String NOTIFICATION_TIMEOUT_PARAM = "notification_timeout_ms"; private static final String NOTIFICATION_TIMESTAMPS_STORE_WINDOW_PARAM = "notification_timestamps_store_window_ms"; + private static final String CHROME_MANAGED_NOTIFICATION_MAX_NUMBER_PARAM = + "chrome_managed_notification_max_number"; + private static final String USER_MANAGED_NOTIFICATION_MAX_NUMBER_PARAM = + "user_managed_notification_max_number"; // Gets the timeout of the price drop notification. public static int getNotificationTimeoutMs() { @@ -36,4 +43,23 @@ } return defaultWindow; } + + // Gets the max allowed number of notifications for specified type in given window. + public static int getMaxAllowedNotificationNumber(@SystemNotificationType int type) { + int defaultNumber = 4; + if (FeatureList.isInitialized()) { + final String param; + if (type == SystemNotificationType.PRICE_DROP_ALERTS_CHROME_MANAGED) { + param = CHROME_MANAGED_NOTIFICATION_MAX_NUMBER_PARAM; + } else if (type == SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED) { + param = USER_MANAGED_NOTIFICATION_MAX_NUMBER_PARAM; + } else { + Log.e(TAG, "Invalid notification type."); + return defaultNumber; + } + return ChromeFeatureList.getFieldTrialParamByFeatureAsInt( + ChromeFeatureList.COMMERCE_PRICE_TRACKING, param, defaultNumber); + } + return defaultNumber; + } } \ No newline at end of file
diff --git a/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java b/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java index 40cfa3bf..8923937 100644 --- a/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java +++ b/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotificationManagerTest.java
@@ -70,7 +70,8 @@ @CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "enable-features=" + ChromeFeatureList.COMMERCE_PRICE_TRACKING + "<Study", "force-fieldtrials=Study/Group", - "force-fieldtrial-params=Study.Group:enable_price_notification/true"}) + "force-fieldtrial-params=Study.Group:enable_price_notification/true" + + "/user_managed_notification_max_number/2"}) @Features.DisableFeatures({ChromeFeatureList.START_SURFACE_ANDROID}) public class PriceDropNotificationManagerTest { // clang-format on @@ -320,4 +321,20 @@ 0, mPriceDropNotificationManager.updateNotificationTimestamps(mockType, false)); assertEquals(1, mPriceDropNotificationManager.updateNotificationTimestamps(mockType, true)); } + + @Test + @MediumTest + public void testHasReachedMaxAllowedNotificationNumber() { + int mockType = SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED; + assertEquals(false, + mPriceDropNotificationManager.hasReachedMaxAllowedNotificationNumber(mockType)); + + mPriceDropNotificationManager.updateNotificationTimestamps(mockType, true); + assertEquals(false, + mPriceDropNotificationManager.hasReachedMaxAllowedNotificationNumber(mockType)); + + mPriceDropNotificationManager.updateNotificationTimestamps(mockType, true); + assertEquals(true, + mPriceDropNotificationManager.hasReachedMaxAllowedNotificationNumber(mockType)); + } }
diff --git a/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifierUnitTest.java b/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifierUnitTest.java index 5b229f7..4fd63d67 100644 --- a/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifierUnitTest.java +++ b/chrome/browser/commerce/price_tracking/android/javatests/src/org/chromium/chrome/browser/price_tracking/PriceDropNotifierUnitTest.java
@@ -8,21 +8,18 @@ import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.app.PendingIntent; import android.content.Context; +import android.content.Intent; import android.graphics.Bitmap; -import androidx.annotation.Nullable; - import org.junit.After; -import org.junit.Assert; import org.junit.Before; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -34,9 +31,6 @@ import org.robolectric.Robolectric; import org.robolectric.Shadows; import org.robolectric.annotation.Config; -import org.robolectric.annotation.Implementation; -import org.robolectric.annotation.Implements; -import org.robolectric.annotation.Resetter; import org.robolectric.shadows.ShadowLog; import org.robolectric.shadows.ShadowPendingIntent; @@ -44,7 +38,6 @@ import org.chromium.base.ContextUtils; import org.chromium.base.test.BaseRobolectricTestRunner; import org.chromium.chrome.browser.init.ChromeBrowserInitializer; -import org.chromium.chrome.browser.notifications.NotificationUmaTracker.ActionType; import org.chromium.chrome.browser.notifications.NotificationUmaTracker.SystemNotificationType; import org.chromium.chrome.browser.price_tracking.PriceDropNotifier.ActionData; import org.chromium.chrome.browser.price_tracking.PriceDropNotifier.NotificationData; @@ -61,8 +54,7 @@ * Unit test for {@link PriceDropNotifier}. */ @RunWith(BaseRobolectricTestRunner.class) -@Config(manifest = Config.NONE, - shadows = {PriceDropNotifierUnitTest.ShadowPriceDropNotificationManager.class}) +@Config(manifest = Config.NONE) public class PriceDropNotifierUnitTest { private static final String TITLE = "title"; private static final String TEXT = "text"; @@ -73,33 +65,6 @@ private static final String ACTION_TEXT_0 = "action_text_0"; private static final String ACTION_TEXT_1 = "action_text_1"; - /** - * Shadow class for {@link PriceDropNotificationManager}. - */ - @Implements(PriceDropNotificationManager.class) - public static class ShadowPriceDropNotificationManager { - static String sLastActionId; - static String sLastUrl; - static String sLastOfferId; - - public ShadowPriceDropNotificationManager() {} - - @Resetter - public static void reset() { - sLastActionId = null; - sLastUrl = null; - sLastOfferId = null; - } - - @Implementation - public void onNotificationActionClicked( - String actionId, String url, @Nullable String offerId) { - sLastActionId = actionId; - sLastUrl = url; - sLastOfferId = offerId; - } - } - static class TestPriceDropNotifier extends PriceDropNotifier { private final ImageFetcher mMockImageFetcher; private final NotificationWrapperBuilder mMockNotificationBuilder; @@ -137,29 +102,39 @@ private ChromeBrowserInitializer mChromeInitializer; @Mock private NotificationWrapper mNotificationWrapper; + @Mock + private PriceDropNotificationManager mPriceDropNotificationManager; @Captor ArgumentCaptor<Callback<Bitmap>> mBitmapCallbackCaptor; - @Captor - ArgumentCaptor<PendingIntentProvider> mPendingIntentProviderCaptor; - PriceDropNotifier mPriceDropNotifier; + Intent mIntent; @Before public void setUp() { ShadowLog.stream = System.out; mPriceDropNotifier = new TestPriceDropNotifier(ContextUtils.getApplicationContext(), mImageFetcher, mNotificationBuilder, mNotificationManagerProxy); + mPriceDropNotifier.setPriceDropNotificationManagerForTesting(mPriceDropNotificationManager); + mIntent = new Intent(); ChromeBrowserInitializer.setForTesting(mChromeInitializer); when(mNotificationBuilder.buildNotificationWrapper()).thenReturn(mNotificationWrapper); + doReturn(false) + .when(mPriceDropNotificationManager) + .hasReachedMaxAllowedNotificationNumber(anyInt()); + doReturn(mIntent) + .when(mPriceDropNotificationManager) + .getNotificationClickIntent(any(), anyInt()); + doReturn(mIntent) + .when(mPriceDropNotificationManager) + .getNotificationActionClickIntent(any(), any(), any(), any(), anyInt()); } @After public void tearDown() { mPriceDropNotifier = null; ChromeBrowserInitializer.setForTesting(null); - ShadowPriceDropNotificationManager.reset(); } private void showNotification() { @@ -207,6 +182,9 @@ verify(mNotificationBuilder, times(0)).setLargeIcon(any()); verifySetNotificationProperties(); verify(mNotificationManagerProxy).notify(any()); + verify(mPriceDropNotificationManager, times(1)) + .updateNotificationTimestamps( + eq(SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED), eq(true)); } @Test @@ -218,6 +196,9 @@ verify(mNotificationBuilder, times(0)).setBigPictureStyle(any(), any()); verifySetNotificationProperties(); verify(mNotificationManagerProxy).notify(any()); + verify(mPriceDropNotificationManager, times(1)) + .updateNotificationTimestamps( + eq(SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED), eq(true)); } @Test @@ -228,31 +209,21 @@ verify(mNotificationBuilder).setBigPictureStyle(any(), eq(TEXT)); verifySetNotificationProperties(); verify(mNotificationManagerProxy).notify(any()); + verify(mPriceDropNotificationManager, times(1)) + .updateNotificationTimestamps( + eq(SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED), eq(true)); } - // TODO(xingliu): Figure out why test framework crashes and enable this. - @Ignore @Test - public void testNotificationTurnOffAlertClick() { - doAnswer(invocation -> { - Runnable task = invocation.getArgument(0); - task.run(); - return null; - }) - .when(mChromeInitializer) - .runNowOrAfterFullBrowserStarted(any()); - showNotification(); + public void testAlreadyReachedMaxNotificationNumber() { + doReturn(true) + .when(mPriceDropNotificationManager) + .hasReachedMaxAllowedNotificationNumber(anyInt()); + showNotification(/*actionDataList=*/null); invokeImageFetcherCallback(null); - verify(mNotificationBuilder) - .addAction(eq(0), eq(ACTION_TEXT_1), mPendingIntentProviderCaptor.capture(), - eq(ActionType.PRICE_DROP_TURN_OFF_ALERT)); - verify(mNotificationBuilder) - .addAction(eq(0), eq(ACTION_TEXT_0), any(), eq(ActionType.PRICE_DROP_VISIT_SITE)); - - sendPendingIntent(mPendingIntentProviderCaptor.getValue().getPendingIntent()); - Assert.assertEquals(PriceDropNotificationManager.ACTION_ID_TURN_OFF_ALERT, - ShadowPriceDropNotificationManager.sLastActionId); - Assert.assertEquals(DESTINATION_URL, ShadowPriceDropNotificationManager.sLastUrl); - Assert.assertEquals(OFFER_ID, ShadowPriceDropNotificationManager.sLastOfferId); + verify(mNotificationManagerProxy, times(0)).notify(any()); + verify(mPriceDropNotificationManager, times(0)) + .updateNotificationTimestamps( + eq(SystemNotificationType.PRICE_DROP_ALERTS_USER_MANAGED), eq(true)); } } \ No newline at end of file
diff --git a/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceConfig.java b/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceConfig.java index 1087bc85..89bc89a 100644 --- a/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceConfig.java +++ b/chrome/browser/commerce/subscriptions/android/java/src/org/chromium/chrome/browser/subscriptions/CommerceSubscriptionsServiceConfig.java
@@ -54,8 +54,8 @@ if (FeatureList.isInitialized()) { return ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean( ChromeFeatureList.COMMERCE_PRICE_TRACKING, IMPLICIT_SUBSCRIPTIONS_ENABLED_PARAM, - true); + false); } - return true; + return false; } }
diff --git a/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/LightweightReactionsProgressDialog.java b/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/LightweightReactionsProgressDialog.java index ea597e3e..d7587aa 100644 --- a/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/LightweightReactionsProgressDialog.java +++ b/chrome/browser/content_creation/reactions/internal/android/java/src/org/chromium/chrome/browser/content_creation/reactions/LightweightReactionsProgressDialog.java
@@ -50,7 +50,12 @@ ApiCompatibilityUtils.getColor(resources, R.color.modern_grey_300)); mProgressBar.setProgressColor( ApiCompatibilityUtils.getColor(resources, R.color.modern_white)); + mProgressBar.setContentDescription( + getActivity().getString(R.string.lightweight_reactions_creating_gif_announcement)); mProgressPercentage = dialogView.findViewById(R.id.reactions_progress_percentage); + // Since the progress bar has a content description, the user does not need to be alerted + // every time the progress bar advances. + mProgressPercentage.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); Button cancelButton = dialogView.findViewById(R.id.reactions_progress_cancel); cancelButton.setOnClickListener(mCancelListener);
diff --git a/chrome/browser/download/download_dir_policy_handler_unittest.cc b/chrome/browser/download/download_dir_policy_handler_unittest.cc index 3e8021c..0f39860 100644 --- a/chrome/browser/download/download_dir_policy_handler_unittest.cc +++ b/chrome/browser/download/download_dir_policy_handler_unittest.cc
@@ -95,12 +95,11 @@ EXPECT_FALSE(value->GetBool()); #endif - std::string download_directory; EXPECT_TRUE(store_->GetValue(prefs::kDownloadDefaultDirectory, &value)); ASSERT_TRUE(value); - EXPECT_TRUE(value->GetAsString(&download_directory)); + ASSERT_TRUE(value->is_string()); EXPECT_EQ(download_dir_util::kDriveNamePolicyVariableName, - download_directory); + value->GetString()); policy.Set(policy::key::kDownloadDirectory, policy::POLICY_LEVEL_MANDATORY, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, @@ -122,10 +121,10 @@ EXPECT_TRUE( recommended_store_->GetValue(prefs::kDownloadDefaultDirectory, &value)); ASSERT_TRUE(value); - EXPECT_TRUE(value->GetAsString(&download_directory)); + ASSERT_TRUE(value->is_string()); EXPECT_EQ(std::string(download_dir_util::kDriveNamePolicyVariableName) + kRelativeToDriveRoot, - download_directory); + value->GetString()); policy.Set(policy::key::kDownloadDirectory, policy::POLICY_LEVEL_RECOMMENDED, policy::POLICY_SCOPE_USER, policy::POLICY_SOURCE_CLOUD, @@ -138,7 +137,7 @@ EXPECT_TRUE( recommended_store_->GetValue(prefs::kDownloadDefaultDirectory, &value)); ASSERT_TRUE(value); - EXPECT_TRUE(value->GetAsString(&download_directory)); - EXPECT_EQ(kUserIDHash, download_directory); + ASSERT_TRUE(value->is_string()); + EXPECT_EQ(kUserIDHash, value->GetString()); } #endif
diff --git a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc index afafd0da..36db0ef 100644 --- a/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc +++ b/chrome/browser/enterprise/connectors/analysis/content_analysis_delegate_browsertest.cc
@@ -5,6 +5,8 @@ #include <memory> #include <set> +#include "base/files/file.h" +#include "base/files/file_util.h" #include "base/path_service.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" @@ -815,9 +817,18 @@ // Create the large file. ContentAnalysisDelegate::Data data; - CreateFilesForTest( - {"large.doc"}, - {std::string(BinaryUploadService::kMaxUploadSizeBytes + 1, 'a')}, &data); + CreateFilesForTest({"large.doc"}, {std::string()}, &data); + + // Write data to the file in chunks to avoid memory allocation errors. + constexpr int64_t kLargeSize = 3ll * 1024ll * 1024ll * 1024ll; + int64_t total_size = 0; + std::string chunk = std::string(48 * 1024 * 1024, 'a'); + base::File file(created_file_paths()[0], + base::File::FLAG_OPEN | base::File::FLAG_WRITE); + while (total_size != kLargeSize) { + file.WriteAtCurrentPos(chunk.data(), chunk.size()); + total_size += chunk.size(); + } ASSERT_TRUE(ContentAnalysisDelegate::IsEnabled( browser()->profile(), GURL(kTestUrl), &data, FILE_ATTACHED)); @@ -826,14 +837,14 @@ validator.ExpectUnscannedFileEvent( /*url*/ "about:blank", /*filename*/ created_file_paths()[0].AsUTF8Unsafe(), - // python3 -c "print('a' * (50 * 1024 * 1024 + 1), end='')" | sha256sum |\ - // tr '[:lower:]' '[:upper:]' + // python3 -c "print('a' * (3 * 1024 * 1024 * 1024), end='')" |\ + // sha256sum | tr '[:lower:]' '[:upper:]' /*sha*/ - "9EB56DB30C49E131459FE735BA6B9D38327376224EC8D5A1233F43A5B4A25942", + "EFC8F27580ADA5D86CFC4451A10A142364DE63A6D70F778F1AC47B284F9D50AA", /*trigger*/ SafeBrowsingPrivateEventRouter::kTriggerFileUpload, /*reason*/ "FILE_TOO_LARGE", /*mimetypes*/ DocMimeTypes(), - /*size*/ BinaryUploadService::kMaxUploadSizeBytes + 1, + /*size*/ kLargeSize, /*result*/ expected_result() ? safe_browsing::EventResultToString( safe_browsing::EventResult::ALLOWED)
diff --git a/chrome/browser/extensions/activity_log/activity_log_unittest.cc b/chrome/browser/extensions/activity_log/activity_log_unittest.cc index 08a9f56..c6fbb2b4 100644 --- a/chrome/browser/extensions/activity_log/activity_log_unittest.cc +++ b/chrome/browser/extensions/activity_log/activity_log_unittest.cc
@@ -90,6 +90,7 @@ std::move(callback).Run(); } void CancelSuspendExtension(const std::string& extension_id) override {} + void SetDeveloperMode(bool current_developer_mode) override {} void SetSessionInfo(version_info::Channel channel, mojom::FeatureSessionType session, bool is_lock_screen_context) override {}
diff --git a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc index bfebc0d1..643b4cb 100644 --- a/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc +++ b/chrome/browser/extensions/api/declarative_content/declarative_content_css_condition_tracker_unittest.cc
@@ -69,6 +69,7 @@ std::move(callback).Run(); } void CancelSuspendExtension(const std::string& extension_id) override {} + void SetDeveloperMode(bool current_developer_mode) override {} void SetSessionInfo(version_info::Channel channel, mojom::FeatureSessionType session, bool is_lock_screen_context) override {}
diff --git a/chrome/browser/extensions/api/developer_private/developer_private_api.cc b/chrome/browser/extensions/api/developer_private/developer_private_api.cc index 6e88c7b..9f36c0cf 100644 --- a/chrome/browser/extensions/api/developer_private/developer_private_api.cc +++ b/chrome/browser/extensions/api/developer_private/developer_private_api.cc
@@ -83,6 +83,7 @@ #include "extensions/browser/notification_types.h" #include "extensions/browser/path_util.h" #include "extensions/browser/process_manager_factory.h" +#include "extensions/browser/renderer_startup_helper.h" #include "extensions/browser/ui_util.h" #include "extensions/browser/warning_service.h" #include "extensions/browser/warning_service_factory.h" @@ -932,6 +933,9 @@ *update.in_developer_mode); SetCurrentDeveloperMode(util::GetBrowserContextId(browser_context()), *update.in_developer_mode); + + RendererStartupHelperFactory::GetForBrowserContext(browser_context()) + ->OnDeveloperModeChanged(*update.in_developer_mode); } return RespondNow(NoArguments());
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 de10972..c22ba1d 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
@@ -82,7 +82,6 @@ } if (input.style != input_ime::MENU_ITEM_STYLE_NONE) { - out->modified |= InputMethodEngine::MENU_ITEM_MODIFIED_STYLE; out->style = static_cast<ash::input_method::InputMethodManager::MenuItemStyle>( input.style);
diff --git a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc index d427c2984..af933d3 100644 --- a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc +++ b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router.cc
@@ -9,6 +9,7 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/json/values_util.h" #include "base/strings/string_number_conversions.h" #include "base/strings/stringprintf.h" #include "base/time/time.h" @@ -358,7 +359,7 @@ // |content_size| can be set to -1 to indicate an unknown size, in // which case the field is not set. if (content_size >= 0) - event.SetIntKey(kKeyContentSize, content_size); + event.SetKey(kKeyContentSize, base::Int64ToValue(content_size)); event.SetStringKey(kKeyTrigger, kTriggerFileDownload); event.SetStringKey( kKeyEventResult, @@ -524,7 +525,7 @@ // |content_size| can be set to -1 to indicate an unknown size, in // which case the field is not set. if (content_size >= 0) - event.SetIntKey(kKeyContentSize, content_size); + event.SetKey(kKeyContentSize, base::Int64ToValue(content_size)); event.SetStringKey(kKeyTrigger, trigger); event.SetStringKey(kKeyEventResult, safe_browsing::EventResultToString(event_result)); @@ -572,7 +573,7 @@ // |content_size| can be set to -1 to indicate an unknown size, in // which case the field is not set. if (content_size >= 0) - event.SetIntKey(kKeyContentSize, content_size); + event.SetKey(kKeyContentSize, base::Int64ToValue(content_size)); event.SetStringKey(kKeyTrigger, trigger); event.SetStringKey(kKeyEventResult, safe_browsing::EventResultToString(event_result)); @@ -617,7 +618,7 @@ // |content_size| can be set to -1 to indicate an unknown size, in // which case the field is not set. if (content_size >= 0) - event.SetIntKey(kKeyContentSize, content_size); + event.SetKey(kKeyContentSize, base::Int64ToValue(content_size)); event.SetStringKey(kKeyTrigger, trigger); event.SetStringKey( kKeyEventResult, @@ -665,7 +666,7 @@ // |content_size| can be set to -1 to indicate an unknown size, in // which case the field is not set. if (content_size >= 0) - event.SetIntKey(kKeyContentSize, content_size); + event.SetKey(kKeyContentSize, base::Int64ToValue(content_size)); event.SetStringKey(kKeyTrigger, trigger); event.SetStringKey(kKeyEventResult, safe_browsing::EventResultToString(event_result)); @@ -717,7 +718,7 @@ // |content_size| can be set to -1 to indicate an unknown size, in // which case the field is not set. if (content_size >= 0) - event.SetIntKey(kKeyContentSize, content_size); + event.SetKey(kKeyContentSize, base::Int64ToValue(content_size)); event.SetStringKey(kKeyTrigger, kTriggerFileDownload); event.SetStringKey(kKeyEventResult, safe_browsing::EventResultToString(event_result)); @@ -770,7 +771,7 @@ // |content_size| can be set to -1 to indicate an unknown size, in // which case the field is not set. if (content_size >= 0) - event.SetIntKey(kKeyContentSize, content_size); + event.SetKey(kKeyContentSize, base::Int64ToValue(content_size)); event.SetStringKey(kKeyTrigger, kTriggerFileDownload); event.SetStringKey( kKeyEventResult,
diff --git a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc index 53e5024..7ce3a72 100644 --- a/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc +++ b/chrome/browser/extensions/api/safe_browsing_private/safe_browsing_private_event_router_unittest.cc
@@ -407,8 +407,8 @@ *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyFileName)); EXPECT_EQ("exe", *event->FindStringKey( SafeBrowsingPrivateEventRouter::kKeyContentType)); - EXPECT_EQ(1234, *event->FindIntKey( - SafeBrowsingPrivateEventRouter::kKeyContentSize)); + EXPECT_EQ("1234", *event->FindStringKey( + SafeBrowsingPrivateEventRouter::kKeyContentSize)); EXPECT_EQ(SafeBrowsingPrivateEventRouter::kTriggerFileDownload, *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyTrigger)); EXPECT_EQ( @@ -532,8 +532,8 @@ *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyFileName)); EXPECT_EQ("exe", *event->FindStringKey( SafeBrowsingPrivateEventRouter::kKeyContentType)); - EXPECT_EQ( - 567, *event->FindIntKey(SafeBrowsingPrivateEventRouter::kKeyContentSize)); + EXPECT_EQ("567", *event->FindStringKey( + SafeBrowsingPrivateEventRouter::kKeyContentSize)); EXPECT_EQ( "POTENTIALLY_UNWANTED", *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyThreatType)); @@ -576,8 +576,8 @@ *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyFileName)); EXPECT_EQ("exe", *event->FindStringKey( SafeBrowsingPrivateEventRouter::kKeyContentType)); - EXPECT_EQ( - 890, *event->FindIntKey(SafeBrowsingPrivateEventRouter::kKeyContentSize)); + EXPECT_EQ("890", *event->FindStringKey( + SafeBrowsingPrivateEventRouter::kKeyContentSize)); EXPECT_EQ( "BYPASSED_WARNING", *event->FindStringKey(SafeBrowsingPrivateEventRouter::kKeyThreatType)); @@ -853,8 +853,8 @@ wrapper.FindKey(SafeBrowsingPrivateEventRouter::kKeySensitiveDataEvent); ASSERT_NE(nullptr, event); - EXPECT_EQ(12345, *event->FindIntKey( - SafeBrowsingPrivateEventRouter::kKeyContentSize)); + EXPECT_EQ("12345", *event->FindStringKey( + SafeBrowsingPrivateEventRouter::kKeyContentSize)); EXPECT_EQ("text/plain", *event->FindStringKey( SafeBrowsingPrivateEventRouter::kKeyContentType)); EXPECT_EQ("sha256_of_data", @@ -906,8 +906,8 @@ wrapper.FindKey(SafeBrowsingPrivateEventRouter::kKeySensitiveDataEvent); ASSERT_NE(nullptr, event); - EXPECT_EQ(12345, *event->FindIntKey( - SafeBrowsingPrivateEventRouter::kKeyContentSize)); + EXPECT_EQ("12345", *event->FindStringKey( + SafeBrowsingPrivateEventRouter::kKeyContentSize)); EXPECT_EQ("text/plain", *event->FindStringKey( SafeBrowsingPrivateEventRouter::kKeyContentType)); EXPECT_EQ("sha256_of_data", @@ -959,8 +959,8 @@ wrapper.FindKey(SafeBrowsingPrivateEventRouter::kKeyUnscannedFileEvent); ASSERT_NE(nullptr, event); - EXPECT_EQ(12345, *event->FindIntKey( - SafeBrowsingPrivateEventRouter::kKeyContentSize)); + EXPECT_EQ("12345", *event->FindStringKey( + SafeBrowsingPrivateEventRouter::kKeyContentSize)); EXPECT_EQ("text/plain", *event->FindStringKey( SafeBrowsingPrivateEventRouter::kKeyContentType)); EXPECT_EQ("sha256_of_data", @@ -1003,8 +1003,8 @@ wrapper.FindKey(SafeBrowsingPrivateEventRouter::kKeyUnscannedFileEvent); ASSERT_NE(nullptr, event); - EXPECT_EQ(12345, *event->FindIntKey( - SafeBrowsingPrivateEventRouter::kKeyContentSize)); + EXPECT_EQ("12345", *event->FindStringKey( + SafeBrowsingPrivateEventRouter::kKeyContentSize)); EXPECT_EQ("text/plain", *event->FindStringKey( SafeBrowsingPrivateEventRouter::kKeyContentType)); EXPECT_EQ("sha256_of_data",
diff --git a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc index 6e3aa4c..303776f 100644 --- a/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc +++ b/chrome/browser/extensions/api/virtual_keyboard_private/chrome_virtual_keyboard_delegate.cc
@@ -573,9 +573,6 @@ "borderedkey", base::FeatureList::IsEnabled( chromeos::features::kVirtualKeyboardBorderedKey))); features.Append(GenerateFeatureFlag( - "assistiveAutoCorrect", - base::FeatureList::IsEnabled(chromeos::features::kAssistAutoCorrect))); - features.Append(GenerateFeatureFlag( "systemchinesephysicaltyping", chromeos::features::IsSystemChinesePhysicalTypingEnabled())); features.Append(GenerateFeatureFlag( @@ -585,9 +582,6 @@ features.Append(GenerateFeatureFlag( "multilingualtyping", base::FeatureList::IsEnabled(chromeos::features::kMultilingualTyping))); - features.Append(GenerateFeatureFlag( - "imeoptionsinsettings", - base::FeatureList::IsEnabled(chromeos::features::kImeOptionsInSettings))); results->SetKey("features", std::move(features));
diff --git a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc index 256d36d..d8148ac 100644 --- a/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc +++ b/chrome/browser/extensions/api/webrtc_audio_private/webrtc_audio_private_browsertest.cc
@@ -178,9 +178,9 @@ // TODO(joi): Verify the contents of these once we start actually // filling them in. - EXPECT_TRUE(dict.HasKey("isDefault")); - EXPECT_TRUE(dict.HasKey("isReady")); - EXPECT_TRUE(dict.HasKey("sampleRate")); + EXPECT_TRUE(dict.FindKey("isDefault")); + EXPECT_TRUE(dict.FindKey("isReady")); + EXPECT_TRUE(dict.FindKey("sampleRate")); } } #endif // BUILDFLAG(IS_MAC)
diff --git a/chrome/browser/extensions/chrome_process_manager_delegate.cc b/chrome/browser/extensions/chrome_process_manager_delegate.cc index a4b33da2..e27edc2f 100644 --- a/chrome/browser/extensions/chrome_process_manager_delegate.cc +++ b/chrome/browser/extensions/chrome_process_manager_delegate.cc
@@ -91,7 +91,7 @@ // For the ChromeOS login profile, only allow apps installed by device // policy or that are explicitly allowlisted. - return login_screen_apps_list->HasKey(extension.id()) || + return login_screen_apps_list->FindKey(extension.id()) || IsComponentExtensionAllowlistedForSignInProfile(extension.id()); }
diff --git a/chrome/browser/extensions/extension_context_menu_model.cc b/chrome/browser/extensions/extension_context_menu_model.cc index 8c6587c..6bb0a8e 100644 --- a/chrome/browser/extensions/extension_context_menu_model.cc +++ b/chrome/browser/extensions/extension_context_menu_model.cc
@@ -251,18 +251,11 @@ const Extension* extension = GetExtension(); if (!extension) return false; - if (ContextMenuMatcher::IsExtensionsCustomCommandId(command_id)) { + + if (ContextMenuMatcher::IsExtensionsCustomCommandId(command_id)) return extension_items_->IsCommandIdVisible(command_id); - } - // The command is hidden in app windows because they don't - // support showing extensions in the app window frame. - if (command_id == TOGGLE_VISIBILITY) { - return (source_ == ContextMenuSource::kToolbarAction) && - can_show_icon_in_toolbar_; - } - - // Standard menu items are visible. + // Items added by Chrome to the menu are always visible. return true; } @@ -283,7 +276,10 @@ return ManifestURL::GetHomepageURL(extension).is_valid() && !is_component_; case OPTIONS: - return OptionsPageInfo::HasOptionsPage(extension); + // Options is always enabled since it will only be visible if it has an + // options page. + DCHECK(OptionsPageInfo::HasOptionsPage(extension)); + return true; case INSPECT_POPUP: { content::WebContents* web_contents = GetActiveWebContents(); return web_contents && extension_action_ && @@ -411,7 +407,7 @@ CreatePageAccessSubmenu(extension); - if (!is_component_ || OptionsPageInfo::HasOptionsPage(extension)) + if (OptionsPageInfo::HasOptionsPage(extension)) AddItemWithStringId(OPTIONS, IDS_EXTENSIONS_OPTIONS_MENU_ITEM); if (!is_component_) { @@ -429,17 +425,18 @@ } } - // Add a toggle visibility (show/hide) if the extension icon is shown on the - // toolbar. - int visibility_string_id = - GetVisibilityStringId(profile_, extension, button_visibility); - DCHECK_NE(-1, visibility_string_id); - AddItemWithStringId(TOGGLE_VISIBILITY, visibility_string_id); - if (IsExtensionForcePinned(*extension, profile_)) { - int toggle_visibility_index = GetIndexOfCommandId(TOGGLE_VISIBILITY); - SetIcon(toggle_visibility_index, - ui::ImageModel::FromVectorIcon(vector_icons::kBusinessIcon, - gfx::kChromeIconGrey, 16)); + if ((source_ == ContextMenuSource::kToolbarAction) && + can_show_icon_in_toolbar_) { + int visibility_string_id = + GetVisibilityStringId(profile_, extension, button_visibility); + DCHECK_NE(-1, visibility_string_id); + AddItemWithStringId(TOGGLE_VISIBILITY, visibility_string_id); + if (IsExtensionForcePinned(*extension, profile_)) { + int toggle_visibility_index = GetIndexOfCommandId(TOGGLE_VISIBILITY); + SetIcon(toggle_visibility_index, + ui::ImageModel::FromVectorIcon(vector_icons::kBusinessIcon, + gfx::kChromeIconGrey, 16)); + } } if (!is_component_) {
diff --git a/chrome/browser/extensions/extension_context_menu_model_unittest.cc b/chrome/browser/extensions/extension_context_menu_model_unittest.cc index f995019..dad98d29 100644 --- a/chrome/browser/extensions/extension_context_menu_model_unittest.cc +++ b/chrome/browser/extensions/extension_context_menu_model_unittest.cc
@@ -255,6 +255,10 @@ // associated with it. content::WebContents* AddTab(const GURL& url); + // Returns the current state for the specified `command` in `menu`. + CommandState GetCommandState(const ExtensionContextMenuModel& menu, + int command) const; + // Returns the current state for the specified page access |command|. CommandState GetPageAccessCommandState(const ExtensionContextMenuModel& menu, int command) const; @@ -351,6 +355,28 @@ } ExtensionContextMenuModelTest::CommandState +ExtensionContextMenuModelTest::GetCommandState( + const ExtensionContextMenuModel& menu, + int command_id) const { + bool is_present = menu.GetIndexOfCommandId(command_id) != -1; + bool is_visible = menu.IsCommandIdVisible(command_id); + + // The command is absent if the menu entry is not present, or the entry is + // present and not visible. + if (!is_present || (is_present && !is_visible)) + return CommandState::kAbsent; + + // The command is disabled if the menu entry is present, visible and is not + // enabled. + bool is_enabled = menu.IsCommandIdEnabled(command_id); + if (is_present && is_visible && !is_enabled) + return CommandState::kDisabled; + + // Otherwise the command is enabled. + return CommandState::kEnabled; +} + +ExtensionContextMenuModelTest::CommandState ExtensionContextMenuModelTest::GetPageAccessCommandState( const ExtensionContextMenuModel& menu, int command) const { @@ -500,8 +526,7 @@ { // Check that a component extension with an options page does have the - // options - // menu item, and it is enabled. + // options menu item, and it is enabled. manifest->SetString("options_page", "options_page.html"); scoped_refptr<const Extension> extension = ExtensionBuilder() @@ -519,61 +544,161 @@ } } -// Tests that the standard menu items (e.g. uninstall, manage) are always -// visible with toolbar action source. +// Tests that the standard menu items (home page, uninstall, and manage +// extensions) are always visible for any context menu source. NOTE: +// other menu items visibility is dependent on context, and behavior is checked +// in other tests. TEST_F(ExtensionContextMenuModelTest, - ExtensionContextMenuStandardItemsAlwaysVisibleWithToolbarActionSource) { + ExtensionContextMenuStandardItemsAlwaysVisible) { InitializeEmptyExtensionService(); const Extension* extension = AddExtension( "extension", manifest_keys::kPageAction, ManifestLocation::kInternal); - ExtensionContextMenuModel menu(extension, GetBrowser(), - ExtensionContextMenuModel::PINNED, nullptr, - true, ContextMenuSource::kToolbarAction); - EXPECT_TRUE(menu.IsCommandIdVisible(ExtensionContextMenuModel::HOME_PAGE)); - EXPECT_TRUE(menu.IsCommandIdVisible(ExtensionContextMenuModel::OPTIONS)); - EXPECT_TRUE( - menu.IsCommandIdVisible(ExtensionContextMenuModel::TOGGLE_VISIBILITY)); - EXPECT_TRUE(menu.IsCommandIdVisible(ExtensionContextMenuModel::UNINSTALL)); - EXPECT_TRUE( - menu.IsCommandIdVisible(ExtensionContextMenuModel::MANAGE_EXTENSIONS)); - EXPECT_TRUE( - menu.IsCommandIdVisible(ExtensionContextMenuModel::INSPECT_POPUP)); - EXPECT_TRUE(menu.IsCommandIdVisible( - ExtensionContextMenuModel::PAGE_ACCESS_RUN_ON_CLICK)); - EXPECT_TRUE(menu.IsCommandIdVisible( - ExtensionContextMenuModel::PAGE_ACCESS_RUN_ON_SITE)); - EXPECT_TRUE(menu.IsCommandIdVisible( - ExtensionContextMenuModel::PAGE_ACCESS_RUN_ON_ALL_SITES)); + std::vector<ContextMenuSource> sources{ContextMenuSource::kToolbarAction, + ContextMenuSource::kMenuItem}; + + for (auto source : sources) { + ExtensionContextMenuModel menu(extension, GetBrowser(), + ExtensionContextMenuModel::PINNED, nullptr, + true, source); + EXPECT_NE(GetCommandState(menu, ExtensionContextMenuModel::HOME_PAGE), + CommandState::kAbsent); + EXPECT_NE(GetCommandState(menu, ExtensionContextMenuModel::UNINSTALL), + CommandState::kAbsent); + EXPECT_NE( + GetCommandState(menu, ExtensionContextMenuModel::MANAGE_EXTENSIONS), + CommandState::kAbsent); + } } -// Tests that the standard menu items (e.g. uninstall, manage) are always -// visible with menu item source. The difference between the menu item and -// toolbar item is that the "pin" option is not shown for the menu item. TEST_F(ExtensionContextMenuModelTest, - ExtensionContextMenuStandardItemsAlwaysVisibleWithMenuItemSource) { + ExtensionContextMenuToggleVisibilityEntryVisibility) { InitializeEmptyExtensionService(); - const Extension* extension = AddExtension( - "extension", manifest_keys::kPageAction, ManifestLocation::kInternal); + scoped_refptr<const Extension> extension = + ExtensionBuilder("extension").Build(); + InitializeAndAddExtension(*extension); - ExtensionContextMenuModel menu(extension, GetBrowser(), - ExtensionContextMenuModel::PINNED, nullptr, - true, ContextMenuSource::kMenuItem); - EXPECT_TRUE(menu.IsCommandIdVisible(ExtensionContextMenuModel::HOME_PAGE)); - EXPECT_TRUE(menu.IsCommandIdVisible(ExtensionContextMenuModel::OPTIONS)); - EXPECT_FALSE( - menu.IsCommandIdVisible(ExtensionContextMenuModel::TOGGLE_VISIBILITY)); - EXPECT_TRUE(menu.IsCommandIdVisible(ExtensionContextMenuModel::UNINSTALL)); - EXPECT_TRUE( - menu.IsCommandIdVisible(ExtensionContextMenuModel::MANAGE_EXTENSIONS)); - EXPECT_TRUE( - menu.IsCommandIdVisible(ExtensionContextMenuModel::INSPECT_POPUP)); - EXPECT_TRUE(menu.IsCommandIdVisible( - ExtensionContextMenuModel::PAGE_ACCESS_RUN_ON_CLICK)); - EXPECT_TRUE(menu.IsCommandIdVisible( - ExtensionContextMenuModel::PAGE_ACCESS_RUN_ON_SITE)); - EXPECT_TRUE(menu.IsCommandIdVisible( - ExtensionContextMenuModel::PAGE_ACCESS_RUN_ON_ALL_SITES)); + { + // Verify the "toggle visibility" entry is absent if the context menu + // source is a menu item. + ExtensionContextMenuModel menu(extension.get(), GetBrowser(), + ExtensionContextMenuModel::PINNED, nullptr, + /* can_show_icon_in_toolbar=*/true, + ContextMenuSource::kMenuItem); + EXPECT_EQ(-1, menu.GetIndexOfCommandId( + ExtensionContextMenuModel::TOGGLE_VISIBILITY)); + EXPECT_EQ( + GetCommandState(menu, ExtensionContextMenuModel::TOGGLE_VISIBILITY), + CommandState::kAbsent); + } + + { + // Verify the "toggle visibility" entry is absent if the context menu + // source is a toolbar action and the icon cannot be shown in the toolbar. + ExtensionContextMenuModel menu(extension.get(), GetBrowser(), + ExtensionContextMenuModel::PINNED, nullptr, + /* can_show_icon_in_toolbar=*/false, + ContextMenuSource::kToolbarAction); + + EXPECT_EQ( + GetCommandState(menu, ExtensionContextMenuModel::TOGGLE_VISIBILITY), + CommandState::kAbsent); + } + + { + // Verify the "toggle visibility" entry is enabled if and only if the + // context menu source is a toolbar action and the icon can be shown in the + // toolbar. + ExtensionContextMenuModel menu(extension.get(), GetBrowser(), + ExtensionContextMenuModel::PINNED, nullptr, + /* can_show_icon_in_toolbar=*/true, + ContextMenuSource::kToolbarAction); + EXPECT_EQ( + GetCommandState(menu, ExtensionContextMenuModel::TOGGLE_VISIBILITY), + CommandState::kEnabled); + } +} + +TEST_F(ExtensionContextMenuModelTest, + ExtensionContextMenuOptionsEntryVisibility) { + InitializeEmptyExtensionService(); + + scoped_refptr<const Extension> extension = + ExtensionBuilder("Extension") + .SetManifestVersion(2) + .SetID(crx_file::id_util::GenerateId("extension")) + .Build(); + service()->AddExtension(extension.get()); + + { + // Verify the "options" entry is absent if the extension doesn't have + // an options page. + ExtensionContextMenuModel menu(extension.get(), GetBrowser(), + ExtensionContextMenuModel::PINNED, nullptr, + true, ContextMenuSource::kToolbarAction); + EXPECT_EQ(GetCommandState(menu, ExtensionContextMenuModel::OPTIONS), + CommandState::kAbsent); + } + + scoped_refptr<const Extension> extension_with_options = + ExtensionBuilder("Extension with options page") + .SetManifestVersion(2) + .SetID(crx_file::id_util::GenerateId("extension_with_options_page")) + .SetManifestKey("options_page", "options_page.html") + .Build(); + service()->AddExtension(extension_with_options.get()); + + { + // Verify the "options" entry is enabled if and only if the + // extension has an options page. + ExtensionContextMenuModel menu(extension_with_options.get(), GetBrowser(), + ExtensionContextMenuModel::PINNED, nullptr, + true, ContextMenuSource::kToolbarAction); + EXPECT_EQ(GetCommandState(menu, ExtensionContextMenuModel::OPTIONS), + CommandState::kEnabled); + } +} + +// TODO(emiliapaz): Currently, the test scenarios always have "inspect popup" +// hidden since the context menu doesn't have a popup delegate and the developer +// mode pref is not set. Add a popup delegate and developer mode pref to +// properly test the "inspect popup" entry visibility. +TEST_F(ExtensionContextMenuModelTest, + ExtensionContextMenuInspectPopupEntryVisibility) { + InitializeEmptyExtensionService(); + { + const Extension* page_action = AddExtension( + "page_action", manifest_keys::kPageAction, ManifestLocation::kInternal); + ASSERT_TRUE(page_action); + ExtensionContextMenuModel menu(page_action, GetBrowser(), + ExtensionContextMenuModel::PINNED, nullptr, + true, ContextMenuSource::kToolbarAction); + EXPECT_EQ(GetCommandState(menu, ExtensionContextMenuModel::INSPECT_POPUP), + CommandState::kAbsent); + } + + { + const Extension* browser_action = + AddExtension("browser_action", manifest_keys::kBrowserAction, + ManifestLocation::kInternal); + ExtensionContextMenuModel menu(browser_action, GetBrowser(), + ExtensionContextMenuModel::PINNED, nullptr, + true, ContextMenuSource::kToolbarAction); + EXPECT_EQ(GetCommandState(menu, ExtensionContextMenuModel::INSPECT_POPUP), + CommandState::kAbsent); + } + + { + // An extension with no specified action has one synthesized. However, + // there will never be a popup to inspect, so we shouldn't add a menu item. + const Extension* no_action = + AddExtension("no_action", nullptr, ManifestLocation::kInternal); + ExtensionContextMenuModel menu(no_action, GetBrowser(), + ExtensionContextMenuModel::PINNED, nullptr, + true, ContextMenuSource::kToolbarAction); + EXPECT_EQ(GetCommandState(menu, ExtensionContextMenuModel::INSPECT_POPUP), + CommandState::kAbsent); + } } // Test that the "pin" and "unpin" menu items appear correctly in the extension @@ -897,44 +1022,6 @@ ExtensionContextMenuModel::PAGE_ACCESS_SUBMENU)); } -TEST_F(ExtensionContextMenuModelTest, TestInspectPopupPresence) { - InitializeEmptyExtensionService(); - { - const Extension* page_action = AddExtension( - "page_action", manifest_keys::kPageAction, ManifestLocation::kInternal); - ASSERT_TRUE(page_action); - ExtensionContextMenuModel menu(page_action, GetBrowser(), - ExtensionContextMenuModel::PINNED, nullptr, - true, ContextMenuSource::kToolbarAction); - int inspect_popup_index = - menu.GetIndexOfCommandId(ExtensionContextMenuModel::INSPECT_POPUP); - EXPECT_GE(0, inspect_popup_index); - } - { - const Extension* browser_action = - AddExtension("browser_action", manifest_keys::kBrowserAction, - ManifestLocation::kInternal); - ExtensionContextMenuModel menu(browser_action, GetBrowser(), - ExtensionContextMenuModel::PINNED, nullptr, - true, ContextMenuSource::kToolbarAction); - int inspect_popup_index = - menu.GetIndexOfCommandId(ExtensionContextMenuModel::INSPECT_POPUP); - EXPECT_GE(0, inspect_popup_index); - } - { - // An extension with no specified action has one synthesized. However, - // there will never be a popup to inspect, so we shouldn't add a menu item. - const Extension* no_action = - AddExtension("no_action", nullptr, ManifestLocation::kInternal); - ExtensionContextMenuModel menu(no_action, GetBrowser(), - ExtensionContextMenuModel::PINNED, nullptr, - true, ContextMenuSource::kToolbarAction); - int inspect_popup_index = - menu.GetIndexOfCommandId(ExtensionContextMenuModel::INSPECT_POPUP); - EXPECT_EQ(-1, inspect_popup_index); - } -} - TEST_F(ExtensionContextMenuModelTest, PageAccessMenuOptions) { InitializeEmptyExtensionService(); @@ -1626,30 +1713,6 @@ 1 /* expected_count */); } -TEST_F(ExtensionContextMenuModelTest, - HideToggleVisibilityWithToolbarActionSource) { - InitializeEmptyExtensionService(); - scoped_refptr<const Extension> extension = - ExtensionBuilder("extension").Build(); - InitializeAndAddExtension(*extension); - { - ExtensionContextMenuModel menu(extension.get(), GetBrowser(), - ExtensionContextMenuModel::PINNED, nullptr, - true /* can_show_icon_in_toolbar */, - ContextMenuSource::kToolbarAction); - EXPECT_TRUE( - menu.IsCommandIdVisible(ExtensionContextMenuModel::TOGGLE_VISIBILITY)); - } - { - ExtensionContextMenuModel menu(extension.get(), GetBrowser(), - ExtensionContextMenuModel::PINNED, nullptr, - false /* can_show_icon_in_toolbar */, - ContextMenuSource::kToolbarAction); - EXPECT_FALSE( - menu.IsCommandIdVisible(ExtensionContextMenuModel::TOGGLE_VISIBILITY)); - } -} - class ExtensionActionContextMenuModelTest : public ExtensionContextMenuModelTest, public testing::WithParamInterface<ActionInfo::Type> {};
diff --git a/chrome/browser/extensions/pending_extension_manager.cc b/chrome/browser/extensions/pending_extension_manager.cc index 68dc1f0..d3874f74 100644 --- a/chrome/browser/extensions/pending_extension_manager.cc +++ b/chrome/browser/extensions/pending_extension_manager.cc
@@ -7,8 +7,14 @@ #include <algorithm> #include "base/containers/contains.h" +#include "base/containers/flat_set.h" +#include "base/feature_list.h" #include "base/logging.h" +#include "base/metrics/histogram_functions.h" #include "base/version.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h" +#include "chrome/common/chrome_features.h" #include "chrome/common/extensions/extension_constants.h" #include "content/public/browser/browser_thread.h" #include "extensions/browser/extension_prefs.h" @@ -123,6 +129,16 @@ return false; } + if (base::FeatureList::IsEnabled( + features::kBlockMigratedDefaultChromeAppSync)) { + EnsureMigratedDefaultChromeAppIdsCachePopulated(); + if (migrating_default_chrome_app_ids_cache_->contains(id)) { + base::UmaHistogramBoolean( + "Extensions.SyncBlockedByDefaultWebAppMigration", true); + return false; + } + } + static const bool kIsFromSync = true; static const mojom::ManifestLocation kSyncLocation = mojom::ManifestLocation::kInternal; @@ -311,6 +327,23 @@ return true; } +void PendingExtensionManager:: + EnsureMigratedDefaultChromeAppIdsCachePopulated() { + if (migrating_default_chrome_app_ids_cache_) + return; + + std::vector<web_app::PreinstalledWebAppMigration> migrations = + web_app::GetPreinstalledWebAppMigrations( + *Profile::FromBrowserContext(context_.get())); + + std::vector<std::string> chrome_app_ids; + chrome_app_ids.reserve(migrations.size()); + for (const web_app::PreinstalledWebAppMigration& migration : migrations) + chrome_app_ids.push_back(migration.old_chrome_app_id); + + migrating_default_chrome_app_ids_cache_.emplace(std::move(chrome_app_ids)); +} + void PendingExtensionManager::AddForTesting( const PendingExtensionInfo& pending_extension_info) { pending_extension_list_.push_back(pending_extension_info);
diff --git a/chrome/browser/extensions/pending_extension_manager.h b/chrome/browser/extensions/pending_extension_manager.h index d20ca3d..fe1184b 100644 --- a/chrome/browser/extensions/pending_extension_manager.h +++ b/chrome/browser/extensions/pending_extension_manager.h
@@ -140,6 +140,10 @@ bool mark_acknowledged, bool remote_install); + // Caches the set of Chrome app IDs undergoing migration to web apps because + // it is expensive to generate every time (multiple SkBitmap copies). + void EnsureMigratedDefaultChromeAppIdsCachePopulated(); + // Add a pending extension record directly. Used for unit tests that need // to set an inital state. Use friendship to allow the tests to call this // method. @@ -150,6 +154,9 @@ PendingExtensionList pending_extension_list_; + absl::optional<base::flat_set<std::string>> + migrating_default_chrome_app_ids_cache_; + FRIEND_TEST_ALL_PREFIXES(ExtensionServiceTest, UpdatePendingExtensionAlreadyInstalled); friend class ExtensionUpdaterTest;
diff --git a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc index 0e63369..d57ea9b 100644 --- a/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc +++ b/chrome/browser/feature_guide/notifications/internal/feature_notification_guide_service_impl.cc
@@ -84,7 +84,7 @@ // Skip low engagement check if enabled. For testing only. if (base::FeatureList::IsEnabled( feature_guide::features::kSkipCheckForLowEngagedUsers)) { - is_low_engaged_user_ = false; + is_low_engaged_user_ = true; return; } @@ -94,7 +94,7 @@ #if BUILDFLAG(IS_ANDROID) if (tracker_->ShouldTriggerHelpUI( feature_engagement::kIPHLowUserEngagementDetectorFeature)) { - is_low_engaged_user_ = false; + is_low_engaged_user_ = true; } #endif return;
diff --git a/chrome/browser/flag-metadata.json b/chrome/browser/flag-metadata.json index 83fd9414..a4e2dd05 100644 --- a/chrome/browser/flag-metadata.json +++ b/chrome/browser/flag-metadata.json
@@ -150,19 +150,14 @@ "expiry_milestone": 102 }, { - "name": "app-management-intent-settings", - "owners": [ "ajlinker", "jshikaram" ], - "expiry_milestone": 96 - }, - { "name": "app-menu-mobile-site-option", "owners": [ "gangwu" ], "expiry_milestone": 96 }, { "name": "apps-shortcut-default-off", - "owners": [ "chrome-desktop-ui-sea@google.com", "cyan" ], - "expiry_milestone": 99 + "owners": [ "chrome-desktop-ui-sea@google.com", "dljames" ], + "expiry_milestone": 102 }, { "name": "arc-account-restrictions", @@ -413,7 +408,7 @@ { "name": "autofill-enable-offer-notification-for-promo-codes", "owners": [ "jsaul@google.com", "siyua" ], - "expiry_milestone": 100 + "expiry_milestone": 105 }, { "name": "autofill-enable-offers-in-clank-keyboard-accessory", @@ -458,7 +453,7 @@ { "name": "autofill-fill-merchant-promo-code-fields", "owners": [ "jsaul@google.com", "payments-autofill-team@google.com" ], - "expiry_milestone": 99 + "expiry_milestone": 105 }, { "name": "autofill-fix-offer-in-incognito", @@ -483,7 +478,7 @@ { "name": "autofill-parse-merchant-promo-code-fields", "owners": [ "jsaul@google.com", "payments-autofill-team@google.com" ], - "expiry_milestone": 102 + "expiry_milestone": 105 }, { "name": "autofill-save-card-dismiss-on-navigation", @@ -785,11 +780,6 @@ "expiry_milestone": 92 }, { - "name": "clipboard-custom-formats", - "owners": ["mek", "snianu@microsoft.com"], - "expiry_milestone": 98 - }, - { "name": "close-all-tabs-modal-dialog", "owners": [ "ckitagawa", "fredmello" ], "expiry_milestone": 103 @@ -1156,11 +1146,6 @@ "expiry_milestone": 101 }, { - "name": "detect-target-embedding-lookalikes", - "owners": [ "jdeblasio", "meacer" ], - "expiry_milestone": 93 - }, - { "name": "detected-source-language-option", "owners": [ "cuianthony", "chrome-language@google.com" ], "expiry_milestone": 97 @@ -1320,7 +1305,7 @@ { "name": "dns-proxy-enable-doh", "owners": [ "garrick", "jasongustaman" ], - "expiry_milestone": 99 + "expiry_milestone": 104 }, { "name": "document-transition", @@ -1826,11 +1811,6 @@ "expiry_milestone": 101 }, { - "name": "enable-desktop-pwas-app-icon-shortcuts-menu-ui", - "owners": [ "ericwilligers@google.com", "desktop-pwas-team@google.com" ], - "expiry_milestone": 98 - }, - { "name": "enable-desktop-pwas-default-offline-page", "owners": [ "catherinecheng@google.com", "anosua@google.com", "ericwilligers@google.com", "alexbn@google.com", "desktop-pwas-team@google.com" ], "expiry_milestone": 110 @@ -1923,7 +1903,7 @@ { "name": "enable-discover-feed-preview", "owners": [ "tinazwang", "sczs" ], - "expiry_milestone": 99 + "expiry_milestone": 101 }, { "name": "enable-discover-feed-shorter-cache", @@ -1938,7 +1918,7 @@ { "name": "enable-dns-proxy", "owners": [ "garrick", "jasongustaman", "cros-networking@google.com" ], - "expiry_milestone": 99 + "expiry_milestone": 104 }, { "name": "enable-docked-magnifier-resizing", @@ -2045,7 +2025,7 @@ { "name": "enable-first-party-sets", "owners": [ "chrome-first-party-sets@chromium.org" ], - "expiry_milestone": 99 + "expiry_milestone": 110 }, { "name": "enable-force-dark", @@ -3393,7 +3373,7 @@ { "name": "forced-colors", "owners": [ "almaher@microsoft.com" ], - "expiry_milestone": 99 + "expiry_milestone": 105 }, { "name": "fractional-scroll-offsets", @@ -3463,6 +3443,11 @@ "expiry_milestone": 104 }, { + "name": "guest-os-files", + "owners": [ "davidmunro@google.com", "clumptini@google.com" ], + "expiry_milestone": 110 + }, + { "name": "handwriting-gesture-editing", "owners": [ "curtismcmullan", "essential-inputs-team@google.com" ], "expiry_milestone": 95
diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc index f0a9cd9..688cf60 100644 --- a/chrome/browser/flag_descriptions.cc +++ b/chrome/browser/flag_descriptions.cc
@@ -578,11 +578,6 @@ const char kContextMenuTranslateWithGoogleLensDescription[] = "Enable a chip for a Translate intent into Google Lens when supported."; -const char kClipboardCustomFormatsName[] = "Clipboard Custom Formats"; -const char kClipboardCustomFormatsDescription[] = - "Allows read/write of custom formats with unsanitized clipboard content. " - "See crbug.com/106449"; - const char kClientStorageAccessContextAuditingName[] = "Access contexts for client-side storage"; const char kClientStorageAccessContextAuditingDescription[] = @@ -690,12 +685,6 @@ const char kDebugShortcutsDescription[] = "Enables additional keyboard shortcuts that are useful for debugging Ash."; -const char kDetectTargetEmbeddingLookalikesName[] = - "Detect target embedding domains as lookalikes."; -const char kDetectTargetEmbeddingLookalikesDescription[] = - "Shows a lookalike interstitial when navigating to target embedding domains" - "(e.g. google.com.example.com)."; - const char kDisableProcessReuse[] = "Disable subframe process reuse"; const char kDisableProcessReuseDescription[] = "Prevents out-of-process iframes from reusing compatible processes from " @@ -823,11 +812,6 @@ "Prefix the window title of installed PWAs with the name of the PWA. On " "ChromeOS this is visible only in the window/activity switcher."; -const char kDesktopPWAsAppIconShortcutsMenuUIName[] = - "Desktop PWAs app icon shortcuts menu UI"; -const char kDesktopPWAsAppIconShortcutsMenuUIDescription[] = - "Show web app shortcuts in the shelf context menu"; - const char kDesktopPWAsRemoveStatusBarName[] = "Desktop PWAs remove status bar"; const char kDesktopPWAsRemoveStatusBarDescription[] = "Hides the status bar popup in Desktop PWA app windows."; @@ -3636,12 +3620,6 @@ "via Presentation API. Requires #cast-media-route-provider to also be " "enabled"; -const char kAppManagementIntentSettingsName[] = - "App Management intent settings"; -const char kAppManagementIntentSettingsDescription[] = - "Enables and displays the intent settings link handling setting for App " - "Management."; - const char kEnableAccessibilityLiveCaptionName[] = "Live Caption"; const char kEnableAccessibilityLiveCaptionDescription[] = "Enables the live caption feature which generates captions for " @@ -4820,6 +4798,12 @@ const char kFuseBoxName[] = "Enable ChromeOS FuseBox service"; const char kFuseBoxDescription[] = "ChromeOS FuseBox service."; +const char kGuestOsFilesName[] = + "Enabled Guest OS Service + file manager integration"; +const char kGuestOsFilesDescription[] = + "The files app sources information about guests from the Guest OS service, " + "instead of querying each type individually"; + const char kHelpAppBackgroundPageName[] = "Help App Background Page"; const char kHelpAppBackgroundPageDescription[] = "Enables the Background page in the help app. The background page is used "
diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h index 8605a0a..8b21a69 100644 --- a/chrome/browser/flag_descriptions.h +++ b/chrome/browser/flag_descriptions.h
@@ -319,9 +319,6 @@ extern const char kContextMenuTranslateWithGoogleLensName[]; extern const char kContextMenuTranslateWithGoogleLensDescription[]; -extern const char kClipboardCustomFormatsName[]; -extern const char kClipboardCustomFormatsDescription[]; - extern const char kClientStorageAccessContextAuditingName[]; extern const char kClientStorageAccessContextAuditingDescription[]; @@ -360,9 +357,6 @@ extern const char kDarkLightTestName[]; extern const char kDarkLightTestDescription[]; -extern const char kDetectTargetEmbeddingLookalikesName[]; -extern const char kDetectTargetEmbeddingLookalikesDescription[]; - extern const char kDisableProcessReuse[]; extern const char kDisableProcessReuseDescription[]; @@ -475,9 +469,6 @@ extern const char kDesktopPWAsAdditionalWindowingControlsName[]; extern const char kDesktopPWAsAdditionalWindowingControlsDescription[]; -extern const char kDesktopPWAsAppIconShortcutsMenuUIName[]; -extern const char kDesktopPWAsAppIconShortcutsMenuUIDescription[]; - extern const char kDesktopPWAsPrefixAppNameInWindowTitleName[]; extern const char kDesktopPWAsPrefixAppNameInWindowTitleDescription[]; @@ -2084,9 +2075,6 @@ extern const char kAllowAllSitesToInitiateMirroringName[]; extern const char kAllowAllSitesToInitiateMirroringDescription[]; -extern const char kAppManagementIntentSettingsName[]; -extern const char kAppManagementIntentSettingsDescription[]; - extern const char kEnableAccessibilityLiveCaptionName[]; extern const char kEnableAccessibilityLiveCaptionDescription[]; @@ -2769,6 +2757,9 @@ extern const char kFuseBoxName[]; extern const char kFuseBoxDescription[]; +extern const char kGuestOsFilesName[]; +extern const char kGuestOsFilesDescription[]; + extern const char kHelpAppBackgroundPageName[]; extern const char kHelpAppBackgroundPageDescription[];
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc index 1efda13..a727bf6 100644 --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -636,7 +636,7 @@ "EnableDuplicateDownloadDialog", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kEnableMixedContentDownloadDialog{ - "EnableMixedContentDownloadDialog", base::FEATURE_DISABLED_BY_DEFAULT}; + "EnableMixedContentDownloadDialog", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kExperimentsForAgsa{"ExperimentsForAgsa", base::FEATURE_ENABLED_BY_DEFAULT};
diff --git a/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java b/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java index 08a1fad..e41be134 100644 --- a/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java +++ b/chrome/browser/gsa/java/src/org/chromium/chrome/browser/gsa/GSAAccountChangeListener.java
@@ -87,9 +87,10 @@ private GSAAccountChangeListener(Context context, GSAHelper gsaHelper) { Context applicationContext = context.getApplicationContext(); - applicationContext.registerReceiver(new AccountChangeBroadcastReceiver(), + ContextUtils.registerExportedBroadcastReceiver(applicationContext, + new AccountChangeBroadcastReceiver(), new IntentFilter(ACCOUNT_UPDATE_BROADCAST_INTENT), - ACCOUNT_UPDATE_BROADCAST_PERMISSION, null); + ACCOUNT_UPDATE_BROADCAST_PERMISSION); createGsaClientAndConnect(applicationContext, gsaHelper);
diff --git a/chrome/browser/hid/hid_chooser_context.cc b/chrome/browser/hid/hid_chooser_context.cc index 8c66e4a5..da96202 100644 --- a/chrome/browser/hid/hid_chooser_context.cc +++ b/chrome/browser/hid/hid_chooser_context.cc
@@ -13,7 +13,11 @@ #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" +#include "build/build_config.h" +#include "build/chromeos_buildflags.h" +#include "chrome/browser/browser_process.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" +#include "chrome/browser/hid/hid_policy_allowed_devices.h" #include "chrome/browser/profiles/profile.h" #include "chrome/grit/generated_resources.h" #include "components/content_settings/core/common/content_settings_types.h" @@ -22,8 +26,12 @@ #include "services/device/public/cpp/hid/hid_blocklist.h" #include "ui/base/l10n/l10n_util.h" +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "chrome/browser/ash/profiles/profile_helper.h" +#include "components/user_manager/user.h" +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + #if BUILDFLAG(ENABLE_EXTENSIONS) -#include "base/containers/contains.h" #include "base/containers/fixed_flat_set.h" #include "base/strings/string_piece.h" #include "extensions/common/constants.h" @@ -37,6 +45,11 @@ constexpr char kHidProductIdKey[] = "product-id"; constexpr char kHidSerialNumberKey[] = "serial-number"; +bool IsPolicyGrantedObject(const base::Value& object) { + return object.is_dict() && object.DictSize() == 1 && + object.FindStringKey(kHidDeviceNameKey); +} + base::Value DeviceInfoToValue(const device::mojom::HidDeviceInfo& device) { base::Value value(base::Value::Type::DICTIONARY); value.SetStringKey( @@ -54,9 +67,57 @@ // and must be granted again each time the device is connected. value.SetStringKey(kHidGuidKey, device.guid); } + DCHECK(!IsPolicyGrantedObject(value)); return value; } +base::Value VendorAndProductIdsToValue(uint16_t vendor_id, + uint16_t product_id) { + base::Value object(base::Value::Type::DICTIONARY); + object.SetStringKey( + kHidDeviceNameKey, + l10n_util::GetStringFUTF16( + IDS_HID_POLICY_DESCRIPTION_FOR_VENDOR_ID_AND_PRODUCT_ID, + base::ASCIIToUTF16(base::StringPrintf("%04X", vendor_id)), + base::ASCIIToUTF16(base::StringPrintf("%04X", product_id)))); + DCHECK(IsPolicyGrantedObject(object)); + return object; +} + +base::Value VendorIdToValue(uint16_t vendor_id) { + base::Value object(base::Value::Type::DICTIONARY); + object.SetStringKey( + kHidDeviceNameKey, + l10n_util::GetStringFUTF16( + IDS_HID_POLICY_DESCRIPTION_FOR_VENDOR_ID, + base::ASCIIToUTF16(base::StringPrintf("%04X", vendor_id)))); + DCHECK(IsPolicyGrantedObject(object)); + return object; +} + +base::Value UsagePageAndUsageToValue(uint16_t usage_page, uint16_t usage) { + base::Value object(base::Value::Type::DICTIONARY); + object.SetStringKey( + kHidDeviceNameKey, + l10n_util::GetStringFUTF16( + IDS_HID_POLICY_DESCRIPTION_FOR_USAGE_AND_USAGE_PAGE, + base::ASCIIToUTF16(base::StringPrintf("%04X", usage)), + base::ASCIIToUTF16(base::StringPrintf("%04X", usage_page)))); + DCHECK(IsPolicyGrantedObject(object)); + return object; +} + +base::Value UsagePageToValue(uint16_t usage_page) { + base::Value object(base::Value::Type::DICTIONARY); + object.SetStringKey( + kHidDeviceNameKey, + l10n_util::GetStringFUTF16( + IDS_HID_POLICY_DESCRIPTION_FOR_USAGE_PAGE, + base::ASCIIToUTF16(base::StringPrintf("%04X", usage_page)))); + DCHECK(IsPolicyGrantedObject(object)); + return object; +} + } // namespace void HidChooserContext::DeviceObserver::OnDeviceAdded( @@ -75,7 +136,9 @@ ContentSettingsType::HID_GUARD, ContentSettingsType::HID_CHOOSER_DATA, HostContentSettingsMapFactory::GetForProfile(profile)), - is_incognito_(profile->IsOffTheRecord()) {} + profile_(profile) { + DCHECK(profile_); +} HidChooserContext::~HidChooserContext() { // Notify observers that the chooser context is about to be destroyed. @@ -123,6 +186,11 @@ } bool HidChooserContext::IsValidObject(const base::Value& object) { + if (IsPolicyGrantedObject(object)) + return true; + + // Other objects must have name, vendor, product, and either a GUID or a + // serial number. if (!object.is_dict() || object.DictSize() != 4 || !object.FindStringKey(kHidDeviceNameKey) || !object.FindIntKey(kHidProductIdKey) || @@ -131,8 +199,11 @@ } const std::string* guid = object.FindStringKey(kHidGuidKey); + if (guid && !guid->empty()) + return true; + const std::string* serial_number = object.FindStringKey(kHidSerialNumberKey); - return (guid && !guid->empty()) || (serial_number && !serial_number->empty()); + return serial_number && !serial_number->empty(); } std::vector<std::unique_ptr<permissions::ObjectPermissionContextBase::Object>> @@ -154,12 +225,65 @@ objects.push_back(std::make_unique<Object>( origin, DeviceInfoToValue(*devices_[guid]), content_settings::SettingSource::SETTING_SOURCE_USER, - is_incognito_)); + IsOffTheRecord())); } } } - // TODO(crbug.com/1049825): Include policy-granted objects. + if (CanApplyPolicy()) { + auto* policy = g_browser_process->hid_policy_allowed_devices(); + for (const auto& entry : policy->device_policy()) { + if (!base::Contains(entry.second, origin)) + continue; + + auto object = + VendorAndProductIdsToValue(entry.first.first, entry.first.second); + objects.push_back(std::make_unique<ObjectPermissionContextBase::Object>( + origin, std::move(object), content_settings::SETTING_SOURCE_POLICY, + IsOffTheRecord())); + } + + for (const auto& entry : policy->vendor_policy()) { + if (!base::Contains(entry.second, origin)) + continue; + + auto object = VendorIdToValue(entry.first); + objects.push_back(std::make_unique<ObjectPermissionContextBase::Object>( + origin, std::move(object), content_settings::SETTING_SOURCE_POLICY, + IsOffTheRecord())); + } + + for (const auto& entry : policy->usage_policy()) { + if (!base::Contains(entry.second, origin)) + continue; + + auto object = + UsagePageAndUsageToValue(entry.first.first, entry.first.second); + objects.push_back(std::make_unique<ObjectPermissionContextBase::Object>( + origin, std::move(object), content_settings::SETTING_SOURCE_POLICY, + IsOffTheRecord())); + } + + for (const auto& entry : policy->usage_page_policy()) { + if (!base::Contains(entry.second, origin)) + continue; + + auto object = UsagePageToValue(entry.first); + objects.push_back(std::make_unique<ObjectPermissionContextBase::Object>( + origin, std::move(object), content_settings::SETTING_SOURCE_POLICY, + IsOffTheRecord())); + } + + if (base::Contains(policy->all_devices_policy(), origin)) { + base::Value object(base::Value::Type::DICTIONARY); + object.SetStringKey( + kHidDeviceNameKey, + l10n_util::GetStringUTF16(IDS_HID_POLICY_DESCRIPTION_FOR_ANY_DEVICE)); + objects.push_back(std::make_unique<ObjectPermissionContextBase::Object>( + origin, std::move(object), content_settings::SETTING_SOURCE_POLICY, + IsOffTheRecord())); + } + } return objects; } @@ -179,11 +303,61 @@ DCHECK(base::Contains(devices_, guid)); objects.push_back(std::make_unique<Object>( origin, DeviceInfoToValue(*devices_[guid]), - content_settings::SettingSource::SETTING_SOURCE_USER, is_incognito_)); + content_settings::SettingSource::SETTING_SOURCE_USER, + IsOffTheRecord())); } } - // TODO(crbug.com/1049825): Include policy-granted objects. + if (CanApplyPolicy()) { + auto* policy = g_browser_process->hid_policy_allowed_devices(); + for (const auto& entry : policy->device_policy()) { + auto object = + VendorAndProductIdsToValue(entry.first.first, entry.first.second); + for (const auto& origin : entry.second) { + objects.push_back(std::make_unique<ObjectPermissionContextBase::Object>( + origin, object.Clone(), content_settings::SETTING_SOURCE_POLICY, + IsOffTheRecord())); + } + } + + for (const auto& entry : policy->vendor_policy()) { + auto object = VendorIdToValue(entry.first); + for (const auto& origin : entry.second) { + objects.push_back(std::make_unique<ObjectPermissionContextBase::Object>( + origin, object.Clone(), content_settings::SETTING_SOURCE_POLICY, + IsOffTheRecord())); + } + } + + for (const auto& entry : policy->usage_policy()) { + auto object = + UsagePageAndUsageToValue(entry.first.first, entry.first.second); + for (const auto& origin : entry.second) { + objects.push_back(std::make_unique<ObjectPermissionContextBase::Object>( + origin, object.Clone(), content_settings::SETTING_SOURCE_POLICY, + IsOffTheRecord())); + } + } + + for (const auto& entry : policy->usage_page_policy()) { + auto object = UsagePageToValue(entry.first); + for (const auto& origin : entry.second) { + objects.push_back(std::make_unique<ObjectPermissionContextBase::Object>( + origin, object.Clone(), content_settings::SETTING_SOURCE_POLICY, + IsOffTheRecord())); + } + } + + base::Value object(base::Value::Type::DICTIONARY); + object.SetStringKey( + kHidDeviceNameKey, + l10n_util::GetStringUTF16(IDS_HID_POLICY_DESCRIPTION_FOR_ANY_DEVICE)); + for (const auto& origin : policy->all_devices_policy()) { + objects.push_back(std::make_unique<ObjectPermissionContextBase::Object>( + origin, object.Clone(), content_settings::SETTING_SOURCE_POLICY, + IsOffTheRecord())); + } + } return objects; } @@ -280,6 +454,12 @@ if (device::HidBlocklist::IsDeviceExcluded(device)) return false; + if (CanApplyPolicy() && + g_browser_process->hid_policy_allowed_devices()->HasDevicePermission( + origin, device)) { + return true; + } + if (!CanRequestObjectPermission(origin)) return false; @@ -289,9 +469,11 @@ return true; } - std::vector<std::unique_ptr<Object>> object_list = GetGrantedObjects(origin); - for (const auto& object : object_list) { + for (const auto& object : + ObjectPermissionContextBase::GetGrantedObjects(origin)) { const base::Value& device_value = object->value; + + // Objects provided by the parent class can be assumed valid. DCHECK(IsValidObject(device_value)); if (device.vendor_id != *device_value.FindIntKey(kHidVendorIdKey) || @@ -508,3 +690,15 @@ observer.OnPermissionRevoked(origin); } } + +bool HidChooserContext::CanApplyPolicy() { +#if BUILDFLAG(IS_CHROMEOS_ASH) + auto* profile_helper = chromeos::ProfileHelper::Get(); + DCHECK(profile_helper); + user_manager::User* user = profile_helper->GetUserByProfile(profile_); + DCHECK(user); + return user->IsAffiliated(); +#else + return true; +#endif +}
diff --git a/chrome/browser/hid/hid_chooser_context.h b/chrome/browser/hid/hid_chooser_context.h index 57e14b85..f1fb70c 100644 --- a/chrome/browser/hid/hid_chooser_context.h +++ b/chrome/browser/hid/hid_chooser_context.h
@@ -13,6 +13,7 @@ #include <vector> #include "base/containers/queue.h" +#include "base/memory/raw_ptr.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "base/unguessable_token.h" @@ -121,6 +122,7 @@ device::mojom::HidManager::GetDevicesCallback callback, std::vector<device::mojom::HidDeviceInfoPtr> devices); void OnHidManagerConnectionError(); + bool CanApplyPolicy(); // HID-specific interface for revoking device permissions. void RevokePersistentDevicePermission( @@ -130,7 +132,11 @@ const url::Origin& origin, const device::mojom::HidDeviceInfo& device); - const bool is_incognito_; + // This raw pointer is safe because instances of this class are created by + // HidChooserContextFactory as KeyedServices that will be destroyed when the + // Profile object is destroyed. + const raw_ptr<Profile> profile_; + bool is_initialized_ = false; base::queue<device::mojom::HidManager::GetDevicesCallback> pending_get_devices_requests_;
diff --git a/chrome/browser/hid/hid_chooser_context_unittest.cc b/chrome/browser/hid/hid_chooser_context_unittest.cc index 2622dee..f063465 100644 --- a/chrome/browser/hid/hid_chooser_context_unittest.cc +++ b/chrome/browser/hid/hid_chooser_context_unittest.cc
@@ -4,546 +4,576 @@ #include "chrome/browser/hid/hid_chooser_context.h" +#include "base/barrier_closure.h" +#include "base/guid.h" +#include "base/json/json_reader.h" #include "base/run_loop.h" +#include "base/scoped_observation.h" #include "base/test/bind.h" #include "base/test/gmock_callback_support.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/test_future.h" +#include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "chrome/browser/content_settings/host_content_settings_map_factory.h" #include "chrome/browser/hid/hid_chooser_context_factory.h" #include "chrome/browser/hid/mock_hid_device_observer.h" +#include "chrome/common/pref_names.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/content_settings/core/browser/host_content_settings_map.h" +#include "components/content_settings/core/common/pref_names.h" #include "components/permissions/test/object_permission_context_base_mock_permission_observer.h" +#include "components/sync_preferences/testing_pref_service_syncable.h" #include "content/public/test/browser_task_environment.h" #include "services/device/public/cpp/hid/fake_hid_manager.h" +#include "services/device/public/cpp/hid/hid_blocklist.h" #include "services/device/public/mojom/hid.mojom.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +#if BUILDFLAG(IS_CHROMEOS_ASH) +#include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" +#include "components/account_id/account_id.h" +#include "components/user_manager/scoped_user_manager.h" +#endif using ::base::test::RunClosure; -using ::testing::_; namespace { +// The device IDs used by the simulated HID device. +constexpr uint16_t kTestVendorId = 0x1234; +constexpr uint16_t kTestProductId = 0xabcd; +constexpr char kTestSerialNumber[] = "serial-number"; +constexpr char kTestProductName[] = "product-name"; +constexpr char kTestPhysicalDeviceId[] = "physical-device-id"; + +// The HID usages assigned to the top-level collection of the simulated device. +constexpr uint16_t kTestUsagePage = device::mojom::kPageGenericDesktop; +constexpr uint16_t kTestUsage = device::mojom::kGenericDesktopGamePad; + +std::unique_ptr<base::Value> ReadJson(base::StringPiece json) { + absl::optional<base::Value> value = base::JSONReader::Read(json); + EXPECT_TRUE(value); + return value ? base::Value::ToUniquePtrValue(std::move(*value)) : nullptr; +} + // Main text fixture. -class HidChooserContextTest : public testing::Test { +class HidChooserContextTestBase { public: - HidChooserContextTest() - : origin_(url::Origin::Create(GURL("https://google.com"))) {} - HidChooserContextTest(const HidChooserContextTest&) = delete; - HidChooserContextTest& operator=(const HidChooserContextTest&) = delete; - ~HidChooserContextTest() override = default; + HidChooserContextTestBase() = default; + HidChooserContextTestBase(const HidChooserContextTestBase&) = delete; + HidChooserContextTestBase& operator=(const HidChooserContextTestBase&) = + delete; + ~HidChooserContextTestBase() = default; - const url::Origin& origin() { return origin_; } - Profile* profile() { return &profile_; } - permissions::MockPermissionObserver& permission_observer() { - return mock_permission_observer_; - } - MockHidDeviceObserver& device_observer() { return mock_device_observer_; } + void DoSetUp(bool is_affiliated) { + constexpr char kTestUserEmail[] = "user@example.com"; +#if BUILDFLAG(IS_CHROMEOS_ASH) + constexpr char kTestUserGaiaId[] = "1111111111"; + auto fake_user_manager = std::make_unique<ash::FakeChromeUserManager>(); + auto* fake_user_manager_ptr = fake_user_manager.get(); + scoped_user_manager_ = std::make_unique<user_manager::ScopedUserManager>( + std::move(fake_user_manager)); - HidChooserContext* GetContext() { - auto* context = HidChooserContextFactory::GetForProfile(&profile_); - if (!observers_added_) { - context->AddObserver(&mock_permission_observer_); - context->AddDeviceObserver(&mock_device_observer_); - observers_added_ = true; - } - return context; - } + auto account_id = + AccountId::FromUserEmailGaiaId(kTestUserEmail, kTestUserGaiaId); + fake_user_manager_ptr->AddUserWithAffiliation(account_id, is_affiliated); + fake_user_manager_ptr->LoginUser(account_id); +#endif // BUILDFLAG(IS_CHROMEOS_ASH) - void SetUp() override { + testing_profile_manager_ = std::make_unique<TestingProfileManager>( + TestingBrowserProcess::GetGlobal()); + ASSERT_TRUE(testing_profile_manager_->SetUp()); + profile_ = testing_profile_manager_->CreateTestingProfile(kTestUserEmail); + ASSERT_TRUE(profile_); + mojo::PendingRemote<device::mojom::HidManager> hid_manager; hid_manager_.Bind(hid_manager.InitWithNewPipeAndPassReceiver()); - auto* chooser_context = HidChooserContextFactory::GetForProfile(&profile_); + context_ = HidChooserContextFactory::GetForProfile(profile_); // Connect the HidManager and ensure we've received the initial enumeration // before continuing. base::RunLoop run_loop; - chooser_context->SetHidManagerForTesting( + context_->SetHidManagerForTesting( std::move(hid_manager), base::BindLambdaForTesting( [&run_loop](std::vector<device::mojom::HidDeviceInfoPtr> devices) { run_loop.Quit(); })); run_loop.Run(); + + scoped_permission_observation_.Observe(context_); + scoped_device_observation_.Observe(context_); } - void TearDown() override { - if (observers_added_) { - auto* context = HidChooserContextFactory::GetForProfile(&profile_); - context->RemoveObserver(&mock_permission_observer_); - context->RemoveDeviceObserver(&mock_device_observer_); - } + void DoTearDown() { + // Because HidBlocklist is a singleton it must be cleared after tests run to + // prevent leakage between tests. + feature_list_.Reset(); + device::HidBlocklist::Get().ResetToDefaultValuesForTest(); } - device::mojom::HidDeviceInfoPtr ConnectEphemeralDevice() { - return hid_manager_.CreateAndAddDevice( - "physical-device-id", 0x1234, 0xabcd, "product-name", - /*serial_number=*/"", device::mojom::HidBusType::kHIDBusTypeUSB); + HidChooserContext* context() { return context_; } + permissions::MockPermissionObserver& permission_observer() { + return permission_observer_; + } + MockHidDeviceObserver& device_observer() { return device_observer_; } + + device::mojom::HidDeviceInfoPtr CreateDevice( + base::StringPiece serial_number) { + auto collection = device::mojom::HidCollectionInfo::New(); + collection->usage = + device::mojom::HidUsageAndPage::New(kTestUsage, kTestUsagePage); + collection->collection_type = device::mojom::kHIDCollectionTypeApplication; + collection->input_reports.push_back( + device::mojom::HidReportDescription::New()); + + auto device = device::mojom::HidDeviceInfo::New(); + device->guid = base::GenerateGUID(); + device->physical_device_id = kTestPhysicalDeviceId; + device->vendor_id = kTestVendorId; + device->product_id = kTestProductId; + device->product_name = kTestProductName; + device->serial_number = std::string{serial_number}; + device->bus_type = device::mojom::HidBusType::kHIDBusTypeUSB; + device->collections.push_back(std::move(collection)); + device->protected_input_report_ids = + device::HidBlocklist::Get().GetProtectedReportIds( + device::HidBlocklist::kReportTypeInput, kTestVendorId, + kTestProductId, device->collections); + device->protected_output_report_ids = + device::HidBlocklist::Get().GetProtectedReportIds( + device::HidBlocklist::kReportTypeOutput, kTestVendorId, + kTestProductId, device->collections); + device->protected_feature_report_ids = + device::HidBlocklist::Get().GetProtectedReportIds( + device::HidBlocklist::kReportTypeFeature, kTestVendorId, + kTestProductId, device->collections); + return device; } - device::mojom::HidDeviceInfoPtr ConnectEphemeralDevice( - std::string product_name) { - return hid_manager_.CreateAndAddDevice( - "physical-device-id", 0x1234, 0xabcd, product_name, - /*serial_number=*/"", device::mojom::HidBusType::kHIDBusTypeUSB); + device::mojom::HidDeviceInfoPtr ConnectEphemeralDeviceBlocking() { + return ConnectDeviceBlocking(CreateDevice(/*serial_number=*/"")); } - device::mojom::HidDeviceInfoPtr ConnectPersistentUsbDevice() { - return hid_manager_.CreateAndAddDevice( - "physical-device-id", 0x1234, 0xabcd, "product-name", "serial-number", - device::mojom::HidBusType::kHIDBusTypeUSB); + device::mojom::HidDeviceInfoPtr ConnectPersistentUsbDeviceBlocking() { + return ConnectDeviceBlocking(CreateDevice(kTestSerialNumber)); } - device::mojom::HidDeviceInfoPtr ConnectPersistentUsbDevice( - std::string product_name) { - return hid_manager_.CreateAndAddDevice( - "physical-device-id", 0x1234, 0xabcd, product_name, "serial-number", - device::mojom::HidBusType::kHIDBusTypeUSB); + device::mojom::HidDeviceInfoPtr ConnectDeviceBlocking( + device::mojom::HidDeviceInfoPtr device) { + base::test::TestFuture<device::mojom::HidDeviceInfoPtr> future_device; + EXPECT_CALL(device_observer_, OnDeviceAdded).WillOnce([&](const auto& d) { + future_device.SetValue(d.Clone()); + }); + hid_manager_.AddDevice(std::move(device)); + return future_device.Take(); } - void ConnectDevice(const device::mojom::HidDeviceInfo& device) { - hid_manager_.AddDevice(device.Clone()); + device::mojom::HidDeviceInfoPtr DisconnectDeviceBlocking( + const std::string& device_guid) { + base::test::TestFuture<device::mojom::HidDeviceInfoPtr> future_device; + EXPECT_CALL(device_observer_, OnDeviceRemoved).WillOnce([&](const auto& d) { + future_device.SetValue(d.Clone()); + }); + hid_manager_.RemoveDevice(device_guid); + return future_device.Take(); } - void DisconnectDevice(const device::mojom::HidDeviceInfo& device) { - hid_manager_.RemoveDevice(device.guid); - } - - void UpdateDevice(const device::mojom::HidDeviceInfo& device) { - hid_manager_.ChangeDevice(device.Clone()); + device::mojom::HidDeviceInfoPtr UpdateDeviceBlocking( + device::mojom::HidDeviceInfoPtr device) { + base::test::TestFuture<device::mojom::HidDeviceInfoPtr> future_device; + EXPECT_CALL(device_observer_, OnDeviceChanged).WillOnce([&](const auto& d) { + future_device.SetValue(d.Clone()); + }); + hid_manager_.ChangeDevice(std::move(device)); + return future_device.Take(); } void SimulateHidManagerConnectionError() { hid_manager_.SimulateConnectionError(); } + void GrantDevicePermissionBlocking( + const url::Origin& origin, + const device::mojom::HidDeviceInfo& device) { + base::RunLoop loop; + EXPECT_CALL(permission_observer_, + OnObjectPermissionChanged( + absl::make_optional(ContentSettingsType::HID_GUARD), + ContentSettingsType::HID_CHOOSER_DATA)) + .WillOnce(RunClosure(loop.QuitClosure())); + context()->GrantDevicePermission(origin, device); + loop.Run(); + } + + void RevokeObjectPermissionBlocking(const url::Origin& origin, + const base::Value& object) { + base::RunLoop loop; + EXPECT_CALL(permission_observer_, + OnObjectPermissionChanged( + absl::make_optional(ContentSettingsType::HID_GUARD), + ContentSettingsType::HID_CHOOSER_DATA)) + .WillOnce(RunClosure(loop.QuitClosure())); + context()->RevokeObjectPermission(origin, object); + loop.Run(); + } + + void SetDynamicBlocklist(base::StringPiece value) { + feature_list_.Reset(); + + std::map<std::string, std::string> parameters; + parameters[device::kWebHidBlocklistAdditions.name] = std::string{value}; + feature_list_.InitWithFeaturesAndParameters( + {{device::kWebHidBlocklist, parameters}}, {}); + + device::HidBlocklist::Get().ResetToDefaultValuesForTest(); + } + + void SetContentSettingDefaultForOrigin(const url::Origin& origin, + ContentSetting content_setting) { + HostContentSettingsMapFactory::GetForProfile(profile_) + ->SetContentSettingDefaultScope(origin.GetURL(), origin.GetURL(), + ContentSettingsType::HID_GUARD, + content_setting); + } + + void SetContentSettingDefaultPolicy(ContentSetting content_setting) { + profile_->GetTestingPrefService()->SetManagedPref( + prefs::kManagedDefaultWebHidGuardSetting, + std::make_unique<base::Value>(content_setting)); + } + + void SetAskForUrlsPolicy(base::StringPiece policy) { + profile_->GetTestingPrefService()->SetManagedPref( + prefs::kManagedWebHidAskForUrls, ReadJson(policy)); + } + + void SetBlockedForUrlsPolicy(base::StringPiece policy) { + profile_->GetTestingPrefService()->SetManagedPref( + prefs::kManagedWebHidBlockedForUrls, ReadJson(policy)); + } + + void SetAllowDevicesForUrlsPolicy(base::StringPiece policy) { + testing_profile_manager_->local_state()->Get()->SetManagedPref( + prefs::kManagedWebHidAllowDevicesForUrls, ReadJson(policy)); + } + + void SetAllowDevicesWithHidUsagesForUrlsPolicy(base::StringPiece policy) { + testing_profile_manager_->local_state()->Get()->SetManagedPref( + prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls, + ReadJson(policy)); + } + + void SetAllowAllDevicesForUrlsPolicy(base::StringPiece policy) { + testing_profile_manager_->local_state()->Get()->SetManagedPref( + prefs::kManagedWebHidAllowAllDevicesForUrls, ReadJson(policy)); + } + private: - url::Origin origin_; device::FakeHidManager hid_manager_; content::BrowserTaskEnvironment task_environment_; - TestingProfile profile_; - permissions::MockPermissionObserver mock_permission_observer_; - MockHidDeviceObserver mock_device_observer_; - bool observers_added_ = false; + base::test::ScopedFeatureList feature_list_; + std::unique_ptr<TestingProfileManager> testing_profile_manager_; + TestingProfile* profile_ = nullptr; + +#if BUILDFLAG(IS_CHROMEOS_ASH) + std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; +#endif + + HidChooserContext* context_; + permissions::MockPermissionObserver permission_observer_; + base::ScopedObservation< + permissions::ObjectPermissionContextBase, + permissions::ObjectPermissionContextBase::PermissionObserver> + scoped_permission_observation_{&permission_observer_}; + MockHidDeviceObserver device_observer_; + base::ScopedObservation<HidChooserContext, + HidChooserContext::DeviceObserver, + &HidChooserContext::AddDeviceObserver, + &HidChooserContext::RemoveDeviceObserver> + scoped_device_observation_{&device_observer_}; +}; + +class HidChooserContextTest : public HidChooserContextTestBase, + public testing::Test { + public: + void SetUp() override { DoSetUp(/*is_affiliated=*/true); } + void TearDown() override { DoTearDown(); } }; } // namespace TEST_F(HidChooserContextTest, GrantAndRevokeEphemeralDevice) { - base::RunLoop device_added_loop; - EXPECT_CALL(device_observer(), OnDeviceAdded(_)) - .WillOnce(RunClosure(device_added_loop.QuitClosure())); + const auto kOrigin = url::Origin::Create(GURL("https://google.com")); - base::RunLoop permission_granted_loop; - EXPECT_CALL(permission_observer(), - OnObjectPermissionChanged( - absl::make_optional(ContentSettingsType::HID_GUARD), - ContentSettingsType::HID_CHOOSER_DATA)) - .WillOnce(RunClosure(permission_granted_loop.QuitClosure())) - .WillOnce([]() { - // Expect a 2nd permission change event when the permission is revoked. - }); + // Connect a device that is only eligible for ephemeral permissions. + auto device = ConnectEphemeralDeviceBlocking(); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); - base::RunLoop permission_revoked_loop; - EXPECT_CALL(permission_observer(), OnPermissionRevoked(origin())) - .WillOnce(RunClosure(permission_revoked_loop.QuitClosure())); - - HidChooserContext* context = GetContext(); - - // 1. Connect a device that is only eligible for ephemeral permissions. - auto device = ConnectEphemeralDevice(); - device_added_loop.Run(); - - EXPECT_FALSE(context->HasDevicePermission(origin(), *device)); - - // 2. Grant an ephemeral permission. - context->GrantDevicePermission(origin(), *device); - permission_granted_loop.Run(); - - EXPECT_TRUE(context->HasDevicePermission(origin(), *device)); + // Grant an ephemeral permission. + GrantDevicePermissionBlocking(kOrigin, *device); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device)); std::vector<std::unique_ptr<HidChooserContext::Object>> origin_objects = - context->GetGrantedObjects(origin()); + context()->GetGrantedObjects(kOrigin); ASSERT_EQ(1u, origin_objects.size()); std::vector<std::unique_ptr<HidChooserContext::Object>> objects = - context->GetAllGrantedObjects(); + context()->GetAllGrantedObjects(); ASSERT_EQ(1u, objects.size()); - EXPECT_EQ(origin().GetURL(), objects[0]->origin); + EXPECT_EQ(kOrigin.GetURL(), objects[0]->origin); EXPECT_EQ(origin_objects[0]->value, objects[0]->value); EXPECT_EQ(content_settings::SettingSource::SETTING_SOURCE_USER, objects[0]->source); EXPECT_FALSE(objects[0]->incognito); - // 3. Revoke the permission. - context->RevokeObjectPermission(origin(), objects[0]->value); - permission_revoked_loop.Run(); - - EXPECT_FALSE(context->HasDevicePermission(origin(), *device)); - origin_objects = context->GetGrantedObjects(origin()); - EXPECT_EQ(0u, origin_objects.size()); - objects = context->GetAllGrantedObjects(); - EXPECT_EQ(0u, objects.size()); + // Revoke the permission. + EXPECT_CALL(permission_observer(), OnPermissionRevoked(kOrigin)); + RevokeObjectPermissionBlocking(kOrigin, objects[0]->value); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); } TEST_F(HidChooserContextTest, GrantAndForgetEphemeralDevice) { - base::RunLoop devices_added_loop; - EXPECT_CALL(device_observer(), OnDeviceAdded(_)) - .WillOnce([] {}) - .WillOnce(RunClosure(devices_added_loop.QuitClosure())); + const auto kOrigin = url::Origin::Create(GURL("https://google.com")); - base::RunLoop permission_granted_loop; + // Connect a device with multiple HID interfaces that is only eligible for + // ephemeral permissions. + auto device1 = ConnectEphemeralDeviceBlocking(); + auto device2 = ConnectEphemeralDeviceBlocking(); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device1)); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device2)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // Grant ephemeral permissions. + GrantDevicePermissionBlocking(kOrigin, *device1); + GrantDevicePermissionBlocking(kOrigin, *device2); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device1)); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device2)); + EXPECT_EQ(2u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(2u, context()->GetAllGrantedObjects().size()); + + // Forget the ephemeral device. + base::RunLoop permissions_revoked_loop; + auto permissions_revoked_barrier = + base::BarrierClosure(2, permissions_revoked_loop.QuitClosure()); + EXPECT_CALL(permission_observer(), OnPermissionRevoked(kOrigin)) + .Times(2) + .WillRepeatedly(RunClosure(permissions_revoked_barrier)); EXPECT_CALL(permission_observer(), OnObjectPermissionChanged( absl::make_optional(ContentSettingsType::HID_GUARD), ContentSettingsType::HID_CHOOSER_DATA)) - .WillOnce([]() {}) - .WillOnce(RunClosure(permission_granted_loop.QuitClosure())) - .WillOnce([]() {}) - .WillOnce([]() {}); + .Times(2); + context()->RevokeDevicePermission(kOrigin, *device1); + permissions_revoked_loop.Run(); - base::RunLoop permission_revoked_loop; - EXPECT_CALL(permission_observer(), OnPermissionRevoked(origin())) - .WillOnce([]() {}) - .WillOnce(RunClosure(permission_revoked_loop.QuitClosure())); - - HidChooserContext* context = GetContext(); - - // 1. Connect a device with multiple HID interfaces that is only eligible for - // ephemeral permissions. - auto device1 = ConnectEphemeralDevice("product_name1"); - auto device2 = ConnectEphemeralDevice("product_name2"); - devices_added_loop.Run(); - - EXPECT_FALSE(context->HasDevicePermission(origin(), *device1)); - EXPECT_FALSE(context->HasDevicePermission(origin(), *device2)); - - // 2. Grant ephemeral permission. - context->GrantDevicePermission(origin(), *device1); - context->GrantDevicePermission(origin(), *device2); - permission_granted_loop.Run(); - - EXPECT_TRUE(context->HasDevicePermission(origin(), *device1)); - EXPECT_TRUE(context->HasDevicePermission(origin(), *device2)); - - std::vector<std::unique_ptr<HidChooserContext::Object>> origin_objects = - context->GetGrantedObjects(origin()); - ASSERT_EQ(2u, origin_objects.size()); - - std::vector<std::unique_ptr<HidChooserContext::Object>> objects = - context->GetAllGrantedObjects(); - ASSERT_EQ(2u, objects.size()); - - // 3. Forget the ephemeral device. - context->RevokeDevicePermission(origin(), *device1); - permission_revoked_loop.Run(); - - EXPECT_FALSE(context->HasDevicePermission(origin(), *device1)); - EXPECT_FALSE(context->HasDevicePermission(origin(), *device2)); - origin_objects = context->GetGrantedObjects(origin()); - EXPECT_EQ(0u, origin_objects.size()); - objects = context->GetAllGrantedObjects(); - EXPECT_EQ(0u, objects.size()); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device1)); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device2)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); } TEST_F(HidChooserContextTest, GrantAndDisconnectEphemeralDevice) { - base::RunLoop device_added_loop; - EXPECT_CALL(device_observer(), OnDeviceAdded(_)) - .WillOnce(RunClosure(device_added_loop.QuitClosure())); + const auto kOrigin = url::Origin::Create(GURL("https://google.com")); - EXPECT_CALL(device_observer(), OnDeviceRemoved(_)); + // Connect a device that is only eligible for ephemeral permissions. + auto device = ConnectEphemeralDeviceBlocking(); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); - base::RunLoop permission_granted_loop; - EXPECT_CALL(permission_observer(), - OnObjectPermissionChanged( - absl::make_optional(ContentSettingsType::HID_GUARD), - ContentSettingsType::HID_CHOOSER_DATA)) - .WillOnce(RunClosure(permission_granted_loop.QuitClosure())) - .WillOnce([]() { - // Expect a 2nd permission change event when the permission is revoked. - }); + // Grant an ephemeral permission. + GrantDevicePermissionBlocking(kOrigin, *device); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device)); - base::RunLoop permission_revoked_loop; - EXPECT_CALL(permission_observer(), OnPermissionRevoked(origin())) - .WillOnce(RunClosure(permission_revoked_loop.QuitClosure())); - - HidChooserContext* context = GetContext(); - - // 1. Connect a device that is only eligible for ephemeral permissions. - auto device = ConnectEphemeralDevice(); - device_added_loop.Run(); - - EXPECT_FALSE(context->HasDevicePermission(origin(), *device)); - - // 2. Grant an ephemeral permission. - context->GrantDevicePermission(origin(), *device); - permission_granted_loop.Run(); - - EXPECT_TRUE(context->HasDevicePermission(origin(), *device)); - - std::vector<std::unique_ptr<HidChooserContext::Object>> origin_objects = - context->GetGrantedObjects(origin()); + auto origin_objects = context()->GetGrantedObjects(kOrigin); ASSERT_EQ(1u, origin_objects.size()); - std::vector<std::unique_ptr<HidChooserContext::Object>> objects = - context->GetAllGrantedObjects(); + auto objects = context()->GetAllGrantedObjects(); ASSERT_EQ(1u, objects.size()); - EXPECT_EQ(origin().GetURL(), objects[0]->origin); + EXPECT_EQ(kOrigin.GetURL(), objects[0]->origin); EXPECT_EQ(origin_objects[0]->value, objects[0]->value); EXPECT_EQ(content_settings::SettingSource::SETTING_SOURCE_USER, objects[0]->source); EXPECT_FALSE(objects[0]->incognito); - // 3. Disconnect the device. Because an ephemeral permission was granted, the + // Disconnect the device. Because an ephemeral permission was granted, the // permission should be revoked on disconnect. - DisconnectDevice(*device); - permission_revoked_loop.Run(); - - EXPECT_FALSE(context->HasDevicePermission(origin(), *device)); - origin_objects = context->GetGrantedObjects(origin()); - EXPECT_EQ(0u, origin_objects.size()); - objects = context->GetAllGrantedObjects(); - EXPECT_EQ(0u, objects.size()); + EXPECT_CALL(permission_observer(), OnPermissionRevoked(kOrigin)); + EXPECT_CALL(permission_observer(), + OnObjectPermissionChanged( + absl::make_optional(ContentSettingsType::HID_GUARD), + ContentSettingsType::HID_CHOOSER_DATA)); + DisconnectDeviceBlocking(device->guid); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); } TEST_F(HidChooserContextTest, GrantDisconnectRevokeUsbPersistentDevice) { - base::RunLoop device_added_loop; - EXPECT_CALL(device_observer(), OnDeviceAdded(_)) - .WillOnce(RunClosure(device_added_loop.QuitClosure())); + const auto kOrigin = url::Origin::Create(GURL("https://google.com")); - base::RunLoop device_removed_loop; - EXPECT_CALL(device_observer(), OnDeviceRemoved(_)) - .WillOnce(RunClosure(device_removed_loop.QuitClosure())); + // Connect a USB device eligible for persistent permissions. + auto device = ConnectPersistentUsbDeviceBlocking(); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); - base::RunLoop permission_granted_loop; - EXPECT_CALL(permission_observer(), - OnObjectPermissionChanged( - absl::make_optional(ContentSettingsType::HID_GUARD), - ContentSettingsType::HID_CHOOSER_DATA)) - .WillOnce(RunClosure(permission_granted_loop.QuitClosure())) - .WillOnce([]() { - // Expect a 2nd permission change event when the permission is revoked. - }); + // Grant a persistent permission. + GrantDevicePermissionBlocking(kOrigin, *device); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device)); - base::RunLoop permission_revoked_loop; - EXPECT_CALL(permission_observer(), OnPermissionRevoked(origin())) - .WillOnce(RunClosure(permission_revoked_loop.QuitClosure())); - - HidChooserContext* context = GetContext(); - - // 1. Connect a USB device eligible for persistent permissions. - auto device = ConnectPersistentUsbDevice(); - device_added_loop.Run(); - - EXPECT_FALSE(context->HasDevicePermission(origin(), *device)); - - // 2. Grant a persistent permission. - context->GrantDevicePermission(origin(), *device); - permission_granted_loop.Run(); - - EXPECT_TRUE(context->HasDevicePermission(origin(), *device)); - - std::vector<std::unique_ptr<HidChooserContext::Object>> origin_objects = - context->GetGrantedObjects(origin()); + auto origin_objects = context()->GetGrantedObjects(kOrigin); ASSERT_EQ(1u, origin_objects.size()); - - std::vector<std::unique_ptr<HidChooserContext::Object>> objects = - context->GetAllGrantedObjects(); + auto objects = context()->GetAllGrantedObjects(); ASSERT_EQ(1u, objects.size()); - EXPECT_EQ(origin().GetURL(), objects[0]->origin); + EXPECT_EQ(kOrigin.GetURL(), objects[0]->origin); EXPECT_EQ(origin_objects[0]->value, objects[0]->value); EXPECT_EQ(content_settings::SettingSource::SETTING_SOURCE_USER, objects[0]->source); EXPECT_FALSE(objects[0]->incognito); - // 3. Disconnect the device. The permission should not be revoked. - DisconnectDevice(*device); - device_removed_loop.Run(); + // Disconnect the device. The permission should not be revoked. + EXPECT_CALL(permission_observer(), OnPermissionRevoked(kOrigin)).Times(0); + DisconnectDeviceBlocking(device->guid); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOrigin).size()); + objects = context()->GetAllGrantedObjects(); + EXPECT_EQ(1u, objects.size()); - EXPECT_TRUE(context->HasDevicePermission(origin(), *device)); + // Revoke the persistent permission. + EXPECT_CALL(permission_observer(), OnPermissionRevoked(kOrigin)); + RevokeObjectPermissionBlocking(kOrigin, objects[0]->value); - // 4. Revoke the persistent permission. - context->RevokeObjectPermission(origin(), objects[0]->value); - permission_revoked_loop.Run(); - - EXPECT_FALSE(context->HasDevicePermission(origin(), *device)); - origin_objects = context->GetGrantedObjects(origin()); - EXPECT_EQ(0u, origin_objects.size()); - objects = context->GetAllGrantedObjects(); - EXPECT_EQ(0u, objects.size()); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); } TEST_F(HidChooserContextTest, GrantForgetUsbPersistentDevice) { - base::RunLoop devices_added_loop; - EXPECT_CALL(device_observer(), OnDeviceAdded(_)) - .WillOnce([]() {}) - .WillOnce(RunClosure(devices_added_loop.QuitClosure())); + const auto kOrigin = url::Origin::Create(GURL("https://google.com")); - base::RunLoop permission_granted_loop; - EXPECT_CALL(permission_observer(), - OnObjectPermissionChanged( - absl::make_optional(ContentSettingsType::HID_GUARD), - ContentSettingsType::HID_CHOOSER_DATA)) - .WillOnce([]() {}) - .WillOnce(RunClosure(permission_granted_loop.QuitClosure())) - .WillOnce([]() {}); - - base::RunLoop permission_revoked_loop; - EXPECT_CALL(permission_observer(), OnPermissionRevoked(origin())) - .WillOnce(RunClosure(permission_revoked_loop.QuitClosure())); - - HidChooserContext* context = GetContext(); - - // 1. Connect a USB device with multiple HID interfaces eligible for + // Connect a USB device with multiple HID interfaces eligible for // persistent permissions. - auto device1 = ConnectPersistentUsbDevice("product_name1"); - auto device2 = ConnectPersistentUsbDevice("product_name2"); - devices_added_loop.Run(); + auto device1 = ConnectPersistentUsbDeviceBlocking(); + auto device2 = ConnectPersistentUsbDeviceBlocking(); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device1)); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device2)); - EXPECT_FALSE(context->HasDevicePermission(origin(), *device1)); - EXPECT_FALSE(context->HasDevicePermission(origin(), *device2)); - - // 2. Grant a persistent permission. - context->GrantDevicePermission(origin(), *device1); - context->GrantDevicePermission(origin(), *device2); - permission_granted_loop.Run(); - - EXPECT_TRUE(context->HasDevicePermission(origin(), *device1)); - EXPECT_TRUE(context->HasDevicePermission(origin(), *device2)); - - std::vector<std::unique_ptr<HidChooserContext::Object>> origin_objects = - context->GetGrantedObjects(origin()); - ASSERT_EQ(1u, origin_objects.size()); - - std::vector<std::unique_ptr<HidChooserContext::Object>> objects = - context->GetAllGrantedObjects(); + // Grant persistent permissions. + GrantDevicePermissionBlocking(kOrigin, *device1); + GrantDevicePermissionBlocking(kOrigin, *device2); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device1)); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device2)); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOrigin).size()); + auto objects = context()->GetAllGrantedObjects(); ASSERT_EQ(1u, objects.size()); - // 3. Forget the device by revoking the persistent permission. - context->RevokeDevicePermission(origin(), *device1); - permission_revoked_loop.Run(); - - EXPECT_FALSE(context->HasDevicePermission(origin(), *device1)); - EXPECT_FALSE(context->HasDevicePermission(origin(), *device2)); - origin_objects = context->GetGrantedObjects(origin()); - EXPECT_EQ(0u, origin_objects.size()); - objects = context->GetAllGrantedObjects(); - EXPECT_EQ(0u, objects.size()); + // Forget the device by revoking the persistent permission. + EXPECT_CALL(permission_observer(), OnPermissionRevoked(kOrigin)); + RevokeObjectPermissionBlocking(kOrigin, objects[0]->value); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device1)); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device2)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); } TEST_F(HidChooserContextTest, GuardPermission) { - base::RunLoop device_added_loop; - EXPECT_CALL(device_observer(), OnDeviceAdded(_)) - .WillOnce(RunClosure(device_added_loop.QuitClosure())); + const auto kOrigin = url::Origin::Create(GURL("https://google.com")); - base::RunLoop permission_granted_loop; - EXPECT_CALL(permission_observer(), - OnObjectPermissionChanged( - absl::make_optional(ContentSettingsType::HID_GUARD), - ContentSettingsType::HID_CHOOSER_DATA)) - .WillOnce(RunClosure(permission_granted_loop.QuitClosure())); + // Connect a device that is only eligible for ephemeral permissions. + auto device = ConnectEphemeralDeviceBlocking(); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); - HidChooserContext* context = GetContext(); + // Grant an ephemeral device permission. + GrantDevicePermissionBlocking(kOrigin, *device); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); - // 1. Connect a device that is only eligible for ephemeral permissions. - auto device = ConnectEphemeralDevice(); - device_added_loop.Run(); + // Set the guard permission to CONTENT_SETTING_BLOCK. + SetContentSettingDefaultForOrigin(kOrigin, CONTENT_SETTING_BLOCK); - // 2. Grant an ephemeral device permission. - context->GrantDevicePermission(origin(), *device); - permission_granted_loop.Run(); - - EXPECT_TRUE(context->HasDevicePermission(origin(), *device)); - - // 3. Set the guard permission to CONTENT_SETTING_BLOCK. - auto* map = HostContentSettingsMapFactory::GetForProfile(profile()); - map->SetContentSettingDefaultScope(origin().GetURL(), origin().GetURL(), - ContentSettingsType::HID_GUARD, - CONTENT_SETTING_BLOCK); - - // 4. Check that the device permission is no longer granted. - EXPECT_FALSE(context->HasDevicePermission(origin(), *device)); - - auto objects = context->GetGrantedObjects(origin()); - EXPECT_EQ(0u, objects.size()); - - auto all_origin_objects = context->GetAllGrantedObjects(); - EXPECT_EQ(0u, all_origin_objects.size()); + // Check that the device permission is no longer granted. + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); } TEST_F(HidChooserContextTest, ConnectionErrorWithEphemeralPermission) { - base::RunLoop device_added_loop; - EXPECT_CALL(device_observer(), OnDeviceAdded(_)) - .WillOnce(RunClosure(device_added_loop.QuitClosure())); + const auto kOrigin = url::Origin::Create(GURL("https://google.com")); - EXPECT_CALL(device_observer(), OnHidManagerConnectionError()); + // Connect a device that is only eligible for ephemeral permissions. + auto device = ConnectEphemeralDeviceBlocking(); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); - base::RunLoop permission_granted_loop; + // Grant an ephemeral device permission. + GrantDevicePermissionBlocking(kOrigin, *device); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); + + // Simulate a connection error. The ephemeral permission should be revoked. + base::RunLoop loop; + EXPECT_CALL(permission_observer(), OnPermissionRevoked(kOrigin)) + .WillOnce(RunClosure(loop.QuitClosure())); EXPECT_CALL(permission_observer(), OnObjectPermissionChanged( absl::make_optional(ContentSettingsType::HID_GUARD), - ContentSettingsType::HID_CHOOSER_DATA)) - .WillOnce(RunClosure(permission_granted_loop.QuitClosure())) - .WillOnce([]() { - // Expect a 2nd permission change event when the permission is revoked. - }); - - base::RunLoop permission_revoked_loop; - EXPECT_CALL(permission_observer(), OnPermissionRevoked(origin())) - .WillOnce(RunClosure(permission_revoked_loop.QuitClosure())); - - HidChooserContext* context = GetContext(); - - // 1. Connect a device that is only eligible for persistent permissions. - auto device = ConnectEphemeralDevice(); - device_added_loop.Run(); - - // 2. Grant an ephemeral device permission. - context->GrantDevicePermission(origin(), *device); - permission_granted_loop.Run(); - - // 3. Simulate a connection error. The ephemeral permission should be revoked. + ContentSettingsType::HID_CHOOSER_DATA)); + EXPECT_CALL(device_observer(), OnHidManagerConnectionError()); SimulateHidManagerConnectionError(); - permission_revoked_loop.Run(); + loop.Run(); - EXPECT_FALSE(context->HasDevicePermission(origin(), *device)); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); } TEST_F(HidChooserContextTest, ConnectionErrorWithPersistentPermission) { - base::RunLoop device_added_loop; - EXPECT_CALL(device_observer(), OnDeviceAdded(_)) - .WillOnce(RunClosure(device_added_loop.QuitClosure())); + const auto kOrigin = url::Origin::Create(GURL("https://google.com")); - base::RunLoop connection_error_loop; + // Connect a USB device eligible for persistent permissions. + auto device = ConnectPersistentUsbDeviceBlocking(); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // Grant a persistent device permission. + GrantDevicePermissionBlocking(kOrigin, *device); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); + + // Simulate a connection error. The persistent permission should not be + // affected. + base::RunLoop loop; EXPECT_CALL(device_observer(), OnHidManagerConnectionError()) - .WillOnce(RunClosure(connection_error_loop.QuitClosure())); - - base::RunLoop permission_granted_loop; + .WillOnce(RunClosure(loop.QuitClosure())); EXPECT_CALL(permission_observer(), OnObjectPermissionChanged( absl::make_optional(ContentSettingsType::HID_GUARD), - ContentSettingsType::HID_CHOOSER_DATA)) - .WillOnce(RunClosure(permission_granted_loop.QuitClosure())) - .WillOnce([]() { - // Expect a 2nd permission change event when the permission is revoked. - }); - - HidChooserContext* context = GetContext(); - - // 1. Connect a device that is only eligible for persistent permissions. - auto device = ConnectPersistentUsbDevice(); - device_added_loop.Run(); - - // 2. Grant a persistent device permission. - context->GrantDevicePermission(origin(), *device); - permission_granted_loop.Run(); - - // 3. Simulate a connection error. The persistent permission should not be - // affected. + ContentSettingsType::HID_CHOOSER_DATA)); SimulateHidManagerConnectionError(); - connection_error_loop.Run(); + loop.Run(); - EXPECT_TRUE(context->HasDevicePermission(origin(), *device)); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); } namespace { @@ -576,49 +606,555 @@ TEST_F(HidChooserContextTest, AddChangeRemoveDevice) { const char kTestGuid[] = "guid"; - HidChooserContext* context = GetContext(); - - EXPECT_FALSE(context->GetDeviceInfo(kTestGuid)); + EXPECT_FALSE(context()->GetDeviceInfo(kTestGuid)); // Connect a partially-initialized device. - base::RunLoop device_added_loop; - EXPECT_CALL(device_observer(), OnDeviceAdded).WillOnce([&](const auto& d) { - EXPECT_EQ(d.guid, kTestGuid); - EXPECT_EQ(d.collections.size(), 1u); - device_added_loop.Quit(); - }); - auto partial_device = CreateDeviceWithOneCollection(kTestGuid); - ConnectDevice(*partial_device); - device_added_loop.Run(); - - auto* device_info = context->GetDeviceInfo(kTestGuid); + auto partial_device = + ConnectDeviceBlocking(CreateDeviceWithOneCollection(kTestGuid)); + EXPECT_EQ(partial_device->guid, kTestGuid); + EXPECT_EQ(partial_device->collections.size(), 1u); + auto* device_info = context()->GetDeviceInfo(kTestGuid); ASSERT_TRUE(device_info); EXPECT_EQ(device_info->collections.size(), 1u); // Update the device to add another collection. - base::RunLoop device_changed_loop; - EXPECT_CALL(device_observer(), OnDeviceChanged).WillOnce([&](const auto& d) { - EXPECT_EQ(d.guid, kTestGuid); - EXPECT_EQ(d.collections.size(), 2u); - device_changed_loop.Quit(); - }); - auto complete_device = CreateDeviceWithTwoCollections(kTestGuid); - UpdateDevice(*complete_device); - device_changed_loop.Run(); - - device_info = context->GetDeviceInfo(kTestGuid); + auto complete_device = + UpdateDeviceBlocking(CreateDeviceWithTwoCollections(kTestGuid)); + EXPECT_EQ(complete_device->guid, kTestGuid); + EXPECT_EQ(complete_device->collections.size(), 2u); + device_info = context()->GetDeviceInfo(kTestGuid); ASSERT_TRUE(device_info); EXPECT_EQ(device_info->collections.size(), 2u); // Disconnect the device. - base::RunLoop device_removed_loop; - EXPECT_CALL(device_observer(), OnDeviceRemoved).WillOnce([&](const auto& d) { - EXPECT_EQ(d.guid, kTestGuid); - EXPECT_EQ(d.collections.size(), 2u); - device_removed_loop.Quit(); - }); - DisconnectDevice(*complete_device); - device_removed_loop.Run(); - - ASSERT_FALSE(context->GetDeviceInfo(kTestGuid)); + auto removed_device = DisconnectDeviceBlocking(complete_device->guid); + EXPECT_EQ(removed_device->guid, kTestGuid); + EXPECT_EQ(removed_device->collections.size(), 2u); + ASSERT_FALSE(context()->GetDeviceInfo(kTestGuid)); } + +namespace { + +struct BlocklistTestData { + const char* blocklist; + bool expect_device_permission; +} kBlocklistTestData[]{ + {nullptr, true}, {"", true}, + {"1234:abcd::::", false}, {"1234:0001::::", true}, + {"1234:::::", false}, {"2468:::::", true}, + {"::0001:0005::", false}, {"::0001:0006::", true}, + {"::0001:::", false}, {"::ff00:::", true}, +}; + +class HidChooserContextBlocklistTest + : public HidChooserContextTestBase, + public testing::TestWithParam<BlocklistTestData> { + public: + HidChooserContextBlocklistTest() = default; + + void SetUp() override { DoSetUp(/*is_affiliated=*/true); } + void TearDown() override { DoTearDown(); } +}; + +} // namespace + +TEST_P(HidChooserContextBlocklistTest, Blocklist) { + const auto kOrigin = url::Origin::Create(GURL("https://google.com")); + + if (GetParam().blocklist) + SetDynamicBlocklist(GetParam().blocklist); + + // Connect a device. + auto device = ConnectPersistentUsbDeviceBlocking(); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // Try to grant permission. + GrantDevicePermissionBlocking(kOrigin, *device); + EXPECT_EQ(GetParam().expect_device_permission, + context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); +} + +INSTANTIATE_TEST_SUITE_P(HidChooserContextBlocklistTestInstance, + HidChooserContextBlocklistTest, + ::testing::ValuesIn(kBlocklistTestData)); + +TEST_F(HidChooserContextTest, PolicyGuardPermission) { + const auto kOrigin = url::Origin::Create(GURL("https://google.com")); + + // Connect a device. + auto device = ConnectPersistentUsbDeviceBlocking(); + EXPECT_TRUE(context()->CanRequestObjectPermission(kOrigin)); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // Grant permission and check that the permission was granted. + GrantDevicePermissionBlocking(kOrigin, *device); + EXPECT_TRUE(context()->CanRequestObjectPermission(kOrigin)); + EXPECT_TRUE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); + + // Set a policy to block access to HID devices. After setting the policy, no + // permissions should be granted and requesting permissions should be blocked. + SetContentSettingDefaultPolicy(CONTENT_SETTING_BLOCK); + EXPECT_FALSE(context()->CanRequestObjectPermission(kOrigin)); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); +} + +TEST_F(HidChooserContextTest, PolicyAskForUrls) { + const auto kAskOrigin = url::Origin::Create(GURL("https://ask.origin")); + const auto kOtherOrigin = url::Origin::Create(GURL("https://other.origin")); + + // Connect a device. + auto device = ConnectPersistentUsbDeviceBlocking(); + EXPECT_TRUE(context()->CanRequestObjectPermission(kAskOrigin)); + EXPECT_TRUE(context()->CanRequestObjectPermission(kOtherOrigin)); + EXPECT_FALSE(context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kOtherOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // Grant permission for kAskOrigin and kOtherOrigin to access |device|. + GrantDevicePermissionBlocking(kAskOrigin, *device); + GrantDevicePermissionBlocking(kOtherOrigin, *device); + EXPECT_TRUE(context()->CanRequestObjectPermission(kAskOrigin)); + EXPECT_TRUE(context()->CanRequestObjectPermission(kOtherOrigin)); + EXPECT_TRUE(context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_TRUE(context()->HasDevicePermission(kOtherOrigin, *device)); + EXPECT_EQ(1u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(2u, context()->GetAllGrantedObjects().size()); + + // Set the default guard policy to "block", overriding the granted + // permissions. + SetContentSettingDefaultPolicy(CONTENT_SETTING_BLOCK); + EXPECT_FALSE(context()->CanRequestObjectPermission(kAskOrigin)); + EXPECT_FALSE(context()->CanRequestObjectPermission(kOtherOrigin)); + EXPECT_FALSE(context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kOtherOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // Set the AskForUrls policy to allow kAskOrigin to request permissions. + // This policy overrides the default guard policy. + SetAskForUrlsPolicy(R"( [ "https://ask.origin" ] )"); + EXPECT_TRUE(context()->CanRequestObjectPermission(kAskOrigin)); + EXPECT_FALSE(context()->CanRequestObjectPermission(kOtherOrigin)); + EXPECT_TRUE(context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kOtherOrigin, *device)); + EXPECT_EQ(1u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); +} + +TEST_F(HidChooserContextTest, PolicyBlockedForUrls) { + const auto kBlockedOrigin = + url::Origin::Create(GURL("https://blocked.origin")); + const auto kOtherOrigin = url::Origin::Create(GURL("https://other.origin")); + + // Connect a device. + auto device = ConnectPersistentUsbDeviceBlocking(); + EXPECT_TRUE(context()->CanRequestObjectPermission(kBlockedOrigin)); + EXPECT_TRUE(context()->CanRequestObjectPermission(kOtherOrigin)); + EXPECT_FALSE(context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kOtherOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // Grant permission for kBlockedOrigin and kOtherOrigin to access |device|. + GrantDevicePermissionBlocking(kBlockedOrigin, *device); + GrantDevicePermissionBlocking(kOtherOrigin, *device); + EXPECT_TRUE(context()->CanRequestObjectPermission(kBlockedOrigin)); + EXPECT_TRUE(context()->CanRequestObjectPermission(kOtherOrigin)); + EXPECT_TRUE(context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_TRUE(context()->HasDevicePermission(kOtherOrigin, *device)); + EXPECT_EQ(1u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(2u, context()->GetAllGrantedObjects().size()); + + // Set the BlockedForUrls policy to block kBlockedOrigin from accessing + // devices or requesting permissions. This policy overrides user-granted + // permissions and the default guard setting. + SetBlockedForUrlsPolicy(R"([ "https://blocked.origin" ])"); + EXPECT_FALSE(context()->CanRequestObjectPermission(kBlockedOrigin)); + EXPECT_TRUE(context()->CanRequestObjectPermission(kOtherOrigin)); + EXPECT_FALSE(context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_TRUE(context()->HasDevicePermission(kOtherOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); +} + +namespace { + +class HidChooserContextAffiliatedTest : public HidChooserContextTestBase, + public testing::TestWithParam<bool> { + public: + HidChooserContextAffiliatedTest() : is_affiliated_(GetParam()) {} + + void SetUp() override { DoSetUp(is_affiliated_); } + void TearDown() override { DoTearDown(); } + + bool is_affiliated() const { return is_affiliated_; } + + private: + bool is_affiliated_; +}; + +} // namespace + +TEST_P(HidChooserContextAffiliatedTest, PolicyAllowForUrls) { + const auto kBlockedOrigin = + url::Origin::Create(GURL("https://blocked.origin")); + const auto kAskOrigin = url::Origin::Create(GURL("https://ask.origin")); + const auto kOtherOrigin = url::Origin::Create(GURL("https://other.origin")); + + // Connect a device. + auto device = ConnectPersistentUsbDeviceBlocking(); + + // Set the default content settings to "block" by policy, and set the + // AskForUrls and BlockedForUrls policies to override the default for + // kAskOrigin and kBlockedOrigin. + SetContentSettingDefaultPolicy(CONTENT_SETTING_BLOCK); + SetAskForUrlsPolicy(R"([ "https://ask.origin" ])"); + SetBlockedForUrlsPolicy(R"([ "https://blocked.origin" ])"); + EXPECT_FALSE(context()->CanRequestObjectPermission(kBlockedOrigin)); + EXPECT_TRUE(context()->CanRequestObjectPermission(kAskOrigin)); + EXPECT_FALSE(context()->CanRequestObjectPermission(kOtherOrigin)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // Set the AllowAllDevicesForUrls policy to grant all three origins permission + // to access any device. + SetAllowAllDevicesForUrlsPolicy(R"( + [ + "https://blocked.origin", + "https://ask.origin", + "https://other.origin" + ])"); + EXPECT_EQ(is_affiliated(), + context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_EQ(is_affiliated(), + context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_EQ(is_affiliated(), + context()->HasDevicePermission(kOtherOrigin, *device)); + if (is_affiliated()) { + EXPECT_EQ(1u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(3u, context()->GetAllGrantedObjects().size()); + } else { + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + } + + // Set the AllowAllDevicesForUrls policy back to the default value. + SetAllowAllDevicesForUrlsPolicy("[]"); + EXPECT_FALSE(context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kOtherOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // Set the AllowDevicesForUrls policy to grant permissions to kAskOrigin and + // kOtherOrigin by matching kTestVendorId and kTestProductId. + SetAllowDevicesForUrlsPolicy(R"( + [ + { + "devices": [{ "vendor_id": 4660, "product_id": 43981 }], + "urls": [ "https://ask.origin", "https://other.origin" ] + } + ])"); + EXPECT_FALSE(context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_EQ(is_affiliated(), + context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_EQ(is_affiliated(), + context()->HasDevicePermission(kOtherOrigin, *device)); + if (is_affiliated()) { + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(2u, context()->GetAllGrantedObjects().size()); + } else { + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + } + + // Set the AllowDevicesForUrls policy to give permissions to kBlockedOrigin. + // This policy overrides the BlockedForUrls policy. + SetAllowDevicesForUrlsPolicy(R"( + [ + { + "devices": [{ "vendor_id": 4660, "product_id": 43981 }], + "urls": [ "https://blocked.origin" ] + } + ])"); + EXPECT_EQ(is_affiliated(), + context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kOtherOrigin, *device)); + if (is_affiliated()) { + EXPECT_EQ(1u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); + } else { + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + } + + // Set the AllowDevicesForUrls policy to grant permission to kOtherOrigin to + // access devices with kTestVendorId and any product ID. A second rule grants + // permission for kAskOrigin to access a different device with the same vendor + // ID and a third rule grants permission for kBlockedOrigin to access a + // different vendor ID. Only the first rule matches the device. + SetAllowDevicesForUrlsPolicy(R"( + [ + { + "devices": [{ "vendor_id": 4660 }], + "urls": [ "https://other.origin" ] + }, + { + "devices": [{ "vendor_id": 4660, "product_id": 1 }], + "urls": [ "https://ask.origin" ] + }, + { + "devices": [{ "vendor_id": 123 }], + "urls": [ "https://blocked.origin" ] + } + ])"); + EXPECT_FALSE(context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_EQ(is_affiliated(), + context()->HasDevicePermission(kOtherOrigin, *device)); + if (is_affiliated()) { + EXPECT_EQ(1u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(3u, context()->GetAllGrantedObjects().size()); + } else { + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + } + + // Set the AllowDevicesForUrls policy back to the default value. + SetAllowDevicesForUrlsPolicy("[]"); + EXPECT_FALSE(context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kOtherOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // Set the AllowDevicesWithHidUsagesForUrls policy to grant permissions to + // kAskOrigin and kOtherOrigin by matching kTestUsagePage and kTestUsage. + SetAllowDevicesWithHidUsagesForUrlsPolicy(R"( + [ + { + "usages": [{ "usage_page": 1, "usage": 5 }], + "urls": [ "https://ask.origin", "https://other.origin" ] + } + ])"); + EXPECT_FALSE(context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_EQ(is_affiliated(), + context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_EQ(is_affiliated(), + context()->HasDevicePermission(kOtherOrigin, *device)); + if (is_affiliated()) { + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(2u, context()->GetAllGrantedObjects().size()); + } else { + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + } + + // Set the AllowDevicesWithHidUsagesForUrls policy to give permissions to + // kBlockedOrigin. This policy overrides the BlockedForUrls policy. + SetAllowDevicesWithHidUsagesForUrlsPolicy(R"( + [ + { + "usages": [{ "usage_page": 1, "usage": 5 }], + "urls": [ "https://blocked.origin" ] + } + ])"); + EXPECT_EQ(is_affiliated(), + context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kOtherOrigin, *device)); + if (is_affiliated()) { + EXPECT_EQ(1u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); + } else { + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + } + + // Set the AllowDevicesWithHidUsagesForUrls policy to grant permission to + // kOtherOrigin to access devices with any usage from kTestUsagePage. A + // second rule grants permission for kAskOrigin to access devices with a + // different usage from kTestUsagePage and a third rule grants permission for + // kBlockedOrigin to access a different usage page. Only the first rule + // matches the device. + SetAllowDevicesWithHidUsagesForUrlsPolicy(R"( + [ + { + "usages": [{ "usage_page": 1 }], + "urls": [ "https://other.origin" ] + }, + { + "usages": [{ "usage_page": 1, "usage": 1 }], + "urls": [ "https://ask.origin" ] + }, + { + "usages": [{ "usage_page": 123 }], + "urls": [ "https://blocked.origin" ] + } + ])"); + EXPECT_FALSE(context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_EQ(is_affiliated(), + context()->HasDevicePermission(kOtherOrigin, *device)); + if (is_affiliated()) { + EXPECT_EQ(1u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(1u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(3u, context()->GetAllGrantedObjects().size()); + } else { + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + } + + // Set the AllowDevicesWithHidUsagesForUrls policy back to the default value. + SetAllowDevicesWithHidUsagesForUrlsPolicy("[]"); + EXPECT_FALSE(context()->HasDevicePermission(kBlockedOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kAskOrigin, *device)); + EXPECT_FALSE(context()->HasDevicePermission(kOtherOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kBlockedOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kAskOrigin).size()); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOtherOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); +} + +TEST_P(HidChooserContextAffiliatedTest, BlocklistOverridesPolicy) { + const auto kOrigin = url::Origin::Create(GURL("https://test.origin")); + + // Set the blocklist to deny access to devices with kTestVendorId and + // kTestProductId. + SetDynamicBlocklist("1234:abcd::::"); + + // Connect a device. + auto device = ConnectPersistentUsbDeviceBlocking(); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // The AllowAllDevicesForUrls policy cannot override the blocklist. + SetAllowAllDevicesForUrlsPolicy(R"([ "https://test.origin" ])"); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + if (is_affiliated()) { + EXPECT_EQ(1u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); + } else { + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + } + + SetAllowAllDevicesForUrlsPolicy("[]"); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // The AllowDevicesForUrls policy cannot override the blocklist. + SetAllowDevicesForUrlsPolicy(R"( + [ + { + "devices": [{ "vendor_id": 4660, "product_id": 43981 }], + "urls": [ "https://test.origin" ] + } + ])"); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + if (is_affiliated()) { + EXPECT_EQ(1u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); + } else { + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + } + + SetAllowDevicesForUrlsPolicy("[]"); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + + // The AllowDevicesWithHidUsagesForUrls policy cannot override the blocklist. + SetAllowDevicesWithHidUsagesForUrlsPolicy(R"( + [ + { + "usages": [{ "usage_page": 1, "usage": 5 }], + "urls": [ "https://test.origin" ] + } + ])"); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + if (is_affiliated()) { + EXPECT_EQ(1u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(1u, context()->GetAllGrantedObjects().size()); + } else { + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); + } + + SetAllowDevicesWithHidUsagesForUrlsPolicy("[]"); + EXPECT_FALSE(context()->HasDevicePermission(kOrigin, *device)); + EXPECT_EQ(0u, context()->GetGrantedObjects(kOrigin).size()); + EXPECT_EQ(0u, context()->GetAllGrantedObjects().size()); +} + +// Boolean parameter means if user is affiliated on the device. Affiliated +// users belong to the domain that owns the device and is only meaningful +// on Chrome OS. +// +// The WebHidAllowDevicesForUrls, WebHidAllowDevicesWithHidUsagesForUrls, and +// WebHidAllowAllDevicesForUrls policies only take effect for affiliated users. +INSTANTIATE_TEST_SUITE_P( + HidChooserContextAffiliatedTestInstance, + HidChooserContextAffiliatedTest, +#if BUILDFLAG(IS_CHROMEOS_ASH) + testing::Values(true, false), +#else + testing::Values(true), +#endif + [](const testing::TestParamInfo<HidChooserContextAffiliatedTest::ParamType>& + info) { return info.param ? "affiliated" : "unaffiliated"; });
diff --git a/chrome/browser/hid/hid_policy_allowed_devices.cc b/chrome/browser/hid/hid_policy_allowed_devices.cc index af35e2d..494e112 100644 --- a/chrome/browser/hid/hid_policy_allowed_devices.cc +++ b/chrome/browser/hid/hid_policy_allowed_devices.cc
@@ -4,8 +4,56 @@ #include "chrome/browser/hid/hid_policy_allowed_devices.h" +#include <string> +#include <vector> + +#include "base/bind.h" +#include "base/containers/contains.h" +#include "base/values.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_registry_simple.h" +#include "components/prefs/pref_service.h" +#include "services/device/public/mojom/hid.mojom.h" +#include "url/gurl.h" + +namespace { + +constexpr char kPrefDevicesKey[] = "devices"; +constexpr char kPrefProductIdKey[] = "product_id"; +constexpr char kPrefUrlsKey[] = "urls"; +constexpr char kPrefUsageKey[] = "usage"; +constexpr char kPrefUsagePageKey[] = "usage_page"; +constexpr char kPrefUsagesKey[] = "usages"; +constexpr char kPrefVendorIdKey[] = "vendor_id"; + +} // namespace + +HidPolicyAllowedDevices::HidPolicyAllowedDevices(PrefService* pref_service) { + pref_change_registrar_.Init(pref_service); + // The lifetime of |pref_change_registrar_| is managed by this class so it is + // safe to use base::Unretained here. + pref_change_registrar_.Add( + prefs::kManagedWebHidAllowAllDevicesForUrls, + base::BindRepeating( + &HidPolicyAllowedDevices::LoadAllowAllDevicesForUrlsPolicy, + base::Unretained(this))); + pref_change_registrar_.Add( + prefs::kManagedWebHidAllowDevicesForUrls, + base::BindRepeating( + &HidPolicyAllowedDevices::LoadAllowDevicesForUrlsPolicy, + base::Unretained(this))); + pref_change_registrar_.Add( + prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls, + base::BindRepeating( + &HidPolicyAllowedDevices::LoadAllowDevicesWithHidUsagesForUrlsPolicy, + base::Unretained(this))); + + LoadAllowAllDevicesForUrlsPolicy(); + LoadAllowDevicesForUrlsPolicy(); + LoadAllowDevicesWithHidUsagesForUrlsPolicy(); +} + +HidPolicyAllowedDevices::~HidPolicyAllowedDevices() = default; // static void HidPolicyAllowedDevices::RegisterLocalStatePrefs( @@ -15,3 +63,149 @@ registry->RegisterListPref( prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls); } + +bool HidPolicyAllowedDevices::HasDevicePermission( + const url::Origin& origin, + const device::mojom::HidDeviceInfo& device) { + if (base::Contains(all_devices_policy_, origin)) + return true; + + auto vendor_it = vendor_policy_.find(device.vendor_id); + if (vendor_it != vendor_policy_.end() && + base::Contains(vendor_it->second, origin)) { + return true; + } + + auto device_it = device_policy_.find({device.vendor_id, device.product_id}); + if (device_it != device_policy_.end() && + base::Contains(device_it->second, origin)) { + return true; + } + + for (const auto& collection : device.collections) { + auto usage_page_it = usage_page_policy_.find(collection->usage->usage_page); + if (usage_page_it != usage_page_policy_.end() && + base::Contains(usage_page_it->second, origin)) { + return true; + } + + auto usage_it = usage_policy_.find( + {collection->usage->usage_page, collection->usage->usage}); + if (usage_it != usage_policy_.end() && + base::Contains(usage_it->second, origin)) { + return true; + } + } + + return false; +} + +void HidPolicyAllowedDevices::LoadAllowAllDevicesForUrlsPolicy() { + all_devices_policy_.clear(); + + const auto* pref_value = pref_change_registrar_.prefs()->Get( + prefs::kManagedWebHidAllowAllDevicesForUrls); + if (!pref_value) + return; + + // The pref value has already been validated by the policy handler, so it is + // safe to assume that |pref_value| follows the policy template. + for (const auto& url_value : pref_value->GetListDeprecated()) { + GURL url(url_value.GetString()); + if (url.is_valid()) + all_devices_policy_.insert(url::Origin::Create(url)); + } +} + +void HidPolicyAllowedDevices::LoadAllowDevicesForUrlsPolicy() { + device_policy_.clear(); + vendor_policy_.clear(); + + const auto* pref_value = pref_change_registrar_.prefs()->Get( + prefs::kManagedWebHidAllowDevicesForUrls); + if (!pref_value) + return; + + // The pref value has already been validated by the policy handler, so it is + // safe to assume that |pref_value| follows the policy template. + for (const auto& item : pref_value->GetListDeprecated()) { + const base::Value* urls_value = item.FindKey(kPrefUrlsKey); + DCHECK(urls_value); + + std::vector<url::Origin> urls; + for (const auto& url_value : urls_value->GetListDeprecated()) { + GURL url(url_value.GetString()); + if (url.is_valid()) + urls.push_back(url::Origin::Create(url)); + } + + if (urls.empty()) + continue; + + const auto* devices_value = item.FindKey(kPrefDevicesKey); + DCHECK(devices_value); + for (const auto& device_value : devices_value->GetListDeprecated()) { + const auto* vendor_id_value = device_value.FindKey(kPrefVendorIdKey); + DCHECK(vendor_id_value); + + const auto* product_id_value = device_value.FindKey(kPrefProductIdKey); + // "product_id" is optional. If it is not specified, the policy matches + // any device with the given vendor ID. + if (product_id_value) { + device_policy_[{vendor_id_value->GetInt(), product_id_value->GetInt()}] + .insert(urls.begin(), urls.end()); + } else { + vendor_policy_[vendor_id_value->GetInt()].insert(urls.begin(), + urls.end()); + } + } + } +} + +void HidPolicyAllowedDevices::LoadAllowDevicesWithHidUsagesForUrlsPolicy() { + usage_policy_.clear(); + usage_page_policy_.clear(); + + const auto* pref_value = pref_change_registrar_.prefs()->Get( + prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls); + if (!pref_value) + return; + + // The pref value has already been validated by the policy handler, so it is + // safe to assume that |pref_value| follows the policy template. + for (const auto& item : pref_value->GetListDeprecated()) { + const base::Value* urls_value = item.FindKey(kPrefUrlsKey); + DCHECK(urls_value); + + std::vector<url::Origin> urls; + for (const auto& url_value : urls_value->GetListDeprecated()) { + GURL url(url_value.GetString()); + if (!url.is_valid()) + continue; + + urls.push_back(url::Origin::Create(url)); + } + + if (urls.empty()) + continue; + + const auto* usages_value = item.FindKey(kPrefUsagesKey); + DCHECK(usages_value); + for (const auto& usage_and_page_value : usages_value->GetListDeprecated()) { + const auto* usage_page_value = + usage_and_page_value.FindKey(kPrefUsagePageKey); + DCHECK(usage_page_value); + + const auto* usage_value = usage_and_page_value.FindKey(kPrefUsageKey); + // "usage" is optional. If "usage" is not specified, the policy matches + // any device containing a top-level collection with the given usage page. + if (usage_value) { + usage_policy_[{usage_page_value->GetInt(), usage_value->GetInt()}] + .insert(urls.begin(), urls.end()); + } else { + usage_page_policy_[usage_page_value->GetInt()].insert(urls.begin(), + urls.end()); + } + } + } +}
diff --git a/chrome/browser/hid/hid_policy_allowed_devices.h b/chrome/browser/hid/hid_policy_allowed_devices.h index 9dba927..ec42c394 100644 --- a/chrome/browser/hid/hid_policy_allowed_devices.h +++ b/chrome/browser/hid/hid_policy_allowed_devices.h
@@ -5,12 +5,75 @@ #ifndef CHROME_BROWSER_HID_HID_POLICY_ALLOWED_DEVICES_H_ #define CHROME_BROWSER_HID_HID_POLICY_ALLOWED_DEVICES_H_ -class PrefRegistrySimple; +#include <map> +#include <set> -// TODO(crbug.com/1049825): Implement HidPolicyAllowedDevices +#include "components/prefs/pref_change_registrar.h" +#include "url/origin.h" + +namespace device::mojom { +class HidDeviceInfo; +} // namespace device::mojom + +class PrefRegistrySimple; +class PrefService; + +// This class is used to maintain and interpret the +// WebHidAllowAllDevicesForUrls, WebHidAllowDevicesForUrls, and +// WebHidAllowDevicesWithHidUsagesForUrls policies. +// +// A PrefChangeRegistrar is used to observe changes to the preference values so +// that the policy can be updated in real-time. class HidPolicyAllowedDevices { public: + using OriginSet = std::set<url::Origin>; + using VendorPolicyMap = std::map<uint16_t, OriginSet>; + using DevicePolicyMap = std::map<std::pair<uint16_t, uint16_t>, OriginSet>; + using UsagePagePolicyMap = std::map<uint16_t, OriginSet>; + using UsagePolicyMap = std::map<std::pair<uint16_t, uint16_t>, OriginSet>; + + explicit HidPolicyAllowedDevices(PrefService* pref_service); + HidPolicyAllowedDevices(const HidPolicyAllowedDevices&) = delete; + HidPolicyAllowedDevices& operator=(const HidPolicyAllowedDevices&) = delete; + ~HidPolicyAllowedDevices(); + static void RegisterLocalStatePrefs(PrefRegistrySimple* registry); + + const VendorPolicyMap& vendor_policy() const { return vendor_policy_; } + const DevicePolicyMap& device_policy() const { return device_policy_; } + const UsagePagePolicyMap& usage_page_policy() const { + return usage_page_policy_; + } + const UsagePolicyMap& usage_policy() const { return usage_policy_; } + const OriginSet& all_devices_policy() const { return all_devices_policy_; } + + // Checks if |origin| is allowed to use |device|. + bool HasDevicePermission(const url::Origin& origin, + const device::mojom::HidDeviceInfo& device); + + private: + void LoadAllowAllDevicesForUrlsPolicy(); + void LoadAllowDevicesForUrlsPolicy(); + void LoadAllowDevicesWithHidUsagesForUrlsPolicy(); + + PrefChangeRegistrar pref_change_registrar_; + + // Stores the current policy configuration for origins allowed to access any + // connected device. + OriginSet all_devices_policy_; + + // Stores the current policy configuration for origins allowed to access + // specific devices identified by vendor and product IDs (device_policy_) or + // all devices from a particular vendor ID (vendor_policy_). + DevicePolicyMap device_policy_; + VendorPolicyMap vendor_policy_; + + // Stores the current policy configuration for origins allowed to access + // devices containing top-level collections with specific HID usages + // (usage_policy_) or any usage from a particular usage page + // (usage_page_policy_). + UsagePolicyMap usage_policy_; + UsagePagePolicyMap usage_page_policy_; }; #endif // CHROME_BROWSER_HID_HID_POLICY_ALLOWED_DEVICES_H_
diff --git a/chrome/browser/hid/hid_policy_allowed_devices_unittest.cc b/chrome/browser/hid/hid_policy_allowed_devices_unittest.cc new file mode 100644 index 0000000..ae47cd12 --- /dev/null +++ b/chrome/browser/hid/hid_policy_allowed_devices_unittest.cc
@@ -0,0 +1,549 @@ +// Copyright 2022 The Chromium 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/hid/hid_policy_allowed_devices.h" + +#include <string> +#include <utility> + +#include "base/json/json_reader.h" +#include "base/strings/string_number_conversions.h" +#include "chrome/browser/prefs/browser_prefs.h" +#include "chrome/common/pref_names.h" +#include "chrome/test/base/testing_profile.h" +#include "components/prefs/pref_service.h" +#include "components/prefs/testing_pref_service.h" +#include "content/public/test/browser_task_environment.h" +#include "services/device/public/cpp/hid/fake_hid_manager.h" +#include "services/device/public/mojom/hid.mojom.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "url/gurl.h" +#include "url/origin.h" + +namespace { + +using ::testing::UnorderedElementsAre; + +base::Value ReadJson(base::StringPiece json) { + base::JSONReader::ValueWithError result = + base::JSONReader::ReadAndReturnValueWithError(json); + EXPECT_TRUE(result.value) << result.error_message; + return result.value ? std::move(*result.value) : base::Value(); +} + +class HidPolicyAllowedDevicesTest : public testing::Test { + public: + HidPolicyAllowedDevicesTest() { RegisterLocalState(local_state_.registry()); } + + ~HidPolicyAllowedDevicesTest() override = default; + + void InitializePolicy() { + EXPECT_FALSE(policy_); + policy_ = std::make_unique<HidPolicyAllowedDevices>(&local_state_); + } + + void SetAllowDevicesForUrlsPrefValue(base::StringPiece policy) { + local_state_.Set(prefs::kManagedWebHidAllowDevicesForUrls, + ReadJson(policy)); + } + + void SetAllowDevicesWithHidUsagesForUrlsPrefValue(base::StringPiece policy) { + local_state_.Set(prefs::kManagedWebHidAllowDevicesWithHidUsagesForUrls, + ReadJson(policy)); + } + + void SetAllowAllDevicesForUrlsPrefValue(base::StringPiece policy) { + local_state_.Set(prefs::kManagedWebHidAllowAllDevicesForUrls, + ReadJson(policy)); + } + + protected: + device::FakeHidManager& hid_manager() { return hid_manager_; } + HidPolicyAllowedDevices* policy() { return policy_.get(); } + + device::mojom::HidDeviceInfoPtr CreateAndAddDevice(uint16_t vendor_id, + uint16_t product_id, + uint16_t usage_page, + uint16_t usage) { + static int next_physical_device_id = 0; + return hid_manager_.CreateAndAddDeviceWithTopLevelUsage( + base::NumberToString(next_physical_device_id++), vendor_id, product_id, + "product-name", "serial-number", + device::mojom::HidBusType::kHIDBusTypeUSB, usage_page, usage); + } + + private: + device::FakeHidManager hid_manager_; + content::BrowserTaskEnvironment task_environment_; + TestingPrefServiceSimple local_state_; + std::unique_ptr<HidPolicyAllowedDevices> policy_; +}; + +} // namespace + +TEST_F(HidPolicyAllowedDevicesTest, InitializeWithMissingPrefValue) { + InitializePolicy(); + + EXPECT_EQ(0u, policy()->all_devices_policy().size()); + EXPECT_EQ(0u, policy()->vendor_policy().size()); + EXPECT_EQ(0u, policy()->device_policy().size()); + EXPECT_EQ(0u, policy()->usage_page_policy().size()); + EXPECT_EQ(0u, policy()->usage_policy().size()); +} + +TEST_F(HidPolicyAllowedDevicesTest, InitializeWithExistingEmptyPrefValue) { + SetAllowDevicesForUrlsPrefValue("[]"); + SetAllowDevicesWithHidUsagesForUrlsPrefValue("[]"); + SetAllowAllDevicesForUrlsPrefValue("[]"); + + InitializePolicy(); + + EXPECT_EQ(0u, policy()->all_devices_policy().size()); + EXPECT_EQ(0u, policy()->vendor_policy().size()); + EXPECT_EQ(0u, policy()->device_policy().size()); + EXPECT_EQ(0u, policy()->usage_page_policy().size()); + EXPECT_EQ(0u, policy()->usage_policy().size()); +} + +namespace { + +constexpr uint16_t kTestVendorId1 = 1234; +constexpr uint16_t kTestVendorId2 = 4321; +constexpr uint16_t kTestProductId1 = 5678; +constexpr uint16_t kTestProductId2 = 8765; +constexpr uint16_t kTestUsagePage1 = 1; +constexpr uint16_t kTestUsagePage2 = 2; +constexpr uint16_t kTestUsage1 = 4; +constexpr uint16_t kTestUsage2 = 5; + +constexpr char kAllowDevicesForUrls[] = R"( + [ + { + "devices": [ + { "vendor_id": 1234, "product_id": 5678 }, + { "vendor_id": 4321 } + ], + "urls": [ "https://origin1" ] + } + ])"; +constexpr char kAllowDevicesWithHidUsagesForUrls[] = R"( + [ + { + "usages": [ + { "usage_page": 1, "usage": 4 }, + { "usage_page": 2 } + ], + "urls": [ "https://origin2" ] + } + ])"; +constexpr char kAllowAllDevicesForUrls[] = R"([ "https://origin3" ])"; + +} // namespace + +TEST_F(HidPolicyAllowedDevicesTest, InitializeWithPrefValues) { + const auto kOrigin1 = url::Origin::Create(GURL("https://origin1")); + const auto kOrigin2 = url::Origin::Create(GURL("https://origin2")); + const auto kOrigin3 = url::Origin::Create(GURL("https://origin3")); + + SetAllowDevicesForUrlsPrefValue(kAllowDevicesForUrls); + SetAllowDevicesWithHidUsagesForUrlsPrefValue( + kAllowDevicesWithHidUsagesForUrls); + SetAllowAllDevicesForUrlsPrefValue(kAllowAllDevicesForUrls); + InitializePolicy(); + + EXPECT_EQ(1u, policy()->device_policy().size()); + EXPECT_EQ(1u, policy()->vendor_policy().size()); + EXPECT_EQ(1u, policy()->usage_page_policy().size()); + EXPECT_EQ(1u, policy()->usage_policy().size()); + EXPECT_EQ(1u, policy()->all_devices_policy().size()); + + const auto device_key = std::make_pair(kTestVendorId1, kTestProductId1); + ASSERT_TRUE(base::Contains(policy()->device_policy(), device_key)); + EXPECT_THAT(policy()->device_policy().at(device_key), + UnorderedElementsAre(kOrigin1)); + + ASSERT_TRUE(base::Contains(policy()->vendor_policy(), kTestVendorId2)); + EXPECT_THAT(policy()->vendor_policy().at(kTestVendorId2), + UnorderedElementsAre(kOrigin1)); + + const auto usage_key = std::make_pair(kTestUsagePage1, kTestUsage1); + ASSERT_TRUE(base::Contains(policy()->usage_policy(), usage_key)); + EXPECT_THAT(policy()->usage_policy().at(usage_key), + UnorderedElementsAre(kOrigin2)); + + ASSERT_TRUE(base::Contains(policy()->usage_page_policy(), kTestUsagePage2)); + EXPECT_THAT(policy()->usage_page_policy().at(kTestUsagePage2), + UnorderedElementsAre(kOrigin2)); + + EXPECT_THAT(policy()->all_devices_policy(), UnorderedElementsAre(kOrigin3)); + + auto device = CreateAndAddDevice(kTestVendorId1, kTestProductId1, + /*usage_page=*/0xff00, /*usage=*/1); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + + device = CreateAndAddDevice(kTestVendorId1, kTestProductId2, + /*usage_page=*/0xff00, /*usage=*/1); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + + device = CreateAndAddDevice(kTestVendorId2, kTestProductId2, + /*usage_page=*/0xff00, /*usage=*/1); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + + device = CreateAndAddDevice(/*vendor_id=*/1, /*product_id=*/1, + kTestUsagePage1, kTestUsage1); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + + device = CreateAndAddDevice(/*vendor_id=*/1, /*product_id=*/1, + kTestUsagePage1, kTestUsage2); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + + device = CreateAndAddDevice(/*vendor_id=*/1, /*product_id=*/1, + kTestUsagePage2, kTestUsage2); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); +} + +TEST_F(HidPolicyAllowedDevicesTest, InitializeWithMissingPrefValuesThenUpdate) { + const auto kOrigin1 = url::Origin::Create(GURL("https://origin1")); + const auto kOrigin2 = url::Origin::Create(GURL("https://origin2")); + const auto kOrigin3 = url::Origin::Create(GURL("https://origin3")); + + InitializePolicy(); + + EXPECT_EQ(0u, policy()->device_policy().size()); + EXPECT_EQ(0u, policy()->vendor_policy().size()); + EXPECT_EQ(0u, policy()->usage_page_policy().size()); + EXPECT_EQ(0u, policy()->usage_policy().size()); + EXPECT_EQ(0u, policy()->all_devices_policy().size()); + + SetAllowDevicesForUrlsPrefValue(kAllowDevicesForUrls); + SetAllowDevicesWithHidUsagesForUrlsPrefValue( + kAllowDevicesWithHidUsagesForUrls); + SetAllowAllDevicesForUrlsPrefValue(kAllowAllDevicesForUrls); + + EXPECT_EQ(1u, policy()->device_policy().size()); + EXPECT_EQ(1u, policy()->vendor_policy().size()); + EXPECT_EQ(1u, policy()->usage_page_policy().size()); + EXPECT_EQ(1u, policy()->usage_policy().size()); + EXPECT_EQ(1u, policy()->all_devices_policy().size()); + + const auto device_key = std::make_pair(kTestVendorId1, kTestProductId1); + ASSERT_TRUE(base::Contains(policy()->device_policy(), device_key)); + EXPECT_THAT(policy()->device_policy().at(device_key), + UnorderedElementsAre(kOrigin1)); + + ASSERT_TRUE(base::Contains(policy()->vendor_policy(), kTestVendorId2)); + EXPECT_THAT(policy()->vendor_policy().at(kTestVendorId2), + UnorderedElementsAre(kOrigin1)); + + const auto usage_key = std::make_pair(kTestUsagePage1, kTestUsage1); + ASSERT_TRUE(base::Contains(policy()->usage_policy(), usage_key)); + EXPECT_THAT(policy()->usage_policy().at(usage_key), + UnorderedElementsAre(kOrigin2)); + + ASSERT_TRUE(base::Contains(policy()->usage_page_policy(), kTestUsagePage2)); + EXPECT_THAT(policy()->usage_page_policy().at(kTestUsagePage2), + UnorderedElementsAre(kOrigin2)); + + EXPECT_THAT(policy()->all_devices_policy(), UnorderedElementsAre(kOrigin3)); + + auto device = CreateAndAddDevice(kTestVendorId1, kTestProductId1, + /*usage_page=*/0xff00, /*usage=*/1); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + + device = CreateAndAddDevice(kTestVendorId1, kTestProductId2, + /*usage_page=*/0xff00, /*usage=*/1); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + + device = CreateAndAddDevice(kTestVendorId2, kTestProductId2, + /*usage_page=*/0xff00, /*usage=*/1); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + + device = CreateAndAddDevice(/*vendor_id=*/1, /*product_id=*/1, + kTestUsagePage1, kTestUsage1); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + + device = CreateAndAddDevice(/*vendor_id=*/1, /*product_id=*/1, + kTestUsagePage1, kTestUsage2); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + + device = CreateAndAddDevice(/*vendor_id=*/1, /*product_id=*/1, + kTestUsagePage2, kTestUsage2); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); +} + +TEST_F(HidPolicyAllowedDevicesTest, InitializeWithPrefValuesThenRemovePolicy) { + SetAllowDevicesForUrlsPrefValue(kAllowDevicesForUrls); + SetAllowDevicesWithHidUsagesForUrlsPrefValue( + kAllowDevicesWithHidUsagesForUrls); + SetAllowAllDevicesForUrlsPrefValue(kAllowAllDevicesForUrls); + InitializePolicy(); + + EXPECT_EQ(1u, policy()->device_policy().size()); + EXPECT_EQ(1u, policy()->vendor_policy().size()); + EXPECT_EQ(1u, policy()->usage_page_policy().size()); + EXPECT_EQ(1u, policy()->usage_policy().size()); + EXPECT_EQ(1u, policy()->all_devices_policy().size()); + + // Change each preference back to the default value. + SetAllowDevicesForUrlsPrefValue("[]"); + SetAllowDevicesWithHidUsagesForUrlsPrefValue("[]"); + SetAllowAllDevicesForUrlsPrefValue("[]"); + + EXPECT_EQ(0u, policy()->device_policy().size()); + EXPECT_EQ(0u, policy()->vendor_policy().size()); + EXPECT_EQ(0u, policy()->usage_page_policy().size()); + EXPECT_EQ(0u, policy()->usage_policy().size()); + EXPECT_EQ(0u, policy()->all_devices_policy().size()); +} + +TEST_F(HidPolicyAllowedDevicesTest, MultipleUrls) { + const auto kOrigin1 = url::Origin::Create(GURL("https://origin1")); + const auto kOrigin2 = url::Origin::Create(GURL("https://origin2")); + + SetAllowDevicesForUrlsPrefValue(R"( + [ + { + "devices": [{ "vendor_id": 1234, "product_id": 5678 }], + "urls": [ + "https://origin1", + "https://origin2" + ] + }, + { + "devices": [{ "vendor_id": 1234 }], + "urls": [ + "https://origin1", + "https://origin2" + ] + } + ])"); + SetAllowDevicesWithHidUsagesForUrlsPrefValue(R"( + [ + { + "usages": [{ "usage_page": 1, "usage": 4 }], + "urls": [ + "https://origin1", + "https://origin2" + ] + }, + { + "usages": [{ "usage_page": 1 }], + "urls": [ + "https://origin1", + "https://origin2" + ] + } + ])"); + SetAllowAllDevicesForUrlsPrefValue(R"( + [ + "https://origin1", + "https://origin2" + ])"); + InitializePolicy(); + + EXPECT_EQ(1u, policy()->device_policy().size()); + EXPECT_EQ(1u, policy()->vendor_policy().size()); + EXPECT_EQ(1u, policy()->usage_page_policy().size()); + EXPECT_EQ(1u, policy()->usage_policy().size()); + EXPECT_EQ(2u, policy()->all_devices_policy().size()); + + const auto device_key = std::make_pair(kTestVendorId1, kTestProductId1); + ASSERT_TRUE(base::Contains(policy()->device_policy(), device_key)); + EXPECT_THAT(policy()->device_policy().at(device_key), + UnorderedElementsAre(kOrigin1, kOrigin2)); + + ASSERT_TRUE(base::Contains(policy()->vendor_policy(), kTestVendorId1)); + EXPECT_THAT(policy()->vendor_policy().at(kTestVendorId1), + UnorderedElementsAre(kOrigin1, kOrigin2)); + + const auto usage_key = std::make_pair(kTestUsagePage1, kTestUsage1); + ASSERT_TRUE(base::Contains(policy()->usage_policy(), usage_key)); + EXPECT_THAT(policy()->usage_policy().at(usage_key), + UnorderedElementsAre(kOrigin1, kOrigin2)); + + ASSERT_TRUE(base::Contains(policy()->usage_page_policy(), kTestUsagePage1)); + EXPECT_THAT(policy()->usage_page_policy().at(kTestUsagePage1), + UnorderedElementsAre(kOrigin1, kOrigin2)); + + EXPECT_THAT(policy()->all_devices_policy(), + UnorderedElementsAre(kOrigin1, kOrigin2)); + + auto device = CreateAndAddDevice(kTestVendorId1, kTestProductId1, + kTestUsagePage1, kTestUsage1); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin2, *device)); +} + +TEST_F(HidPolicyAllowedDevicesTest, MultipleItemsWithOverlap) { + const auto kOrigin1 = url::Origin::Create(GURL("https://origin1")); + const auto kOrigin2 = url::Origin::Create(GURL("https://origin2")); + const auto kOrigin3 = url::Origin::Create(GURL("https://origin3")); + const auto kOrigin4 = url::Origin::Create(GURL("https://origin4")); + + SetAllowDevicesForUrlsPrefValue(R"( + [ + { + "devices": [ + { "vendor_id": 1234, "product_id": 5678 }, + { "vendor_id": 4321 } + ], + "urls": [ "https://origin1" ] + }, + { + "devices": [ + { "vendor_id": 1234 }, + { "vendor_id": 4321, "product_id": 8765 } + ], + "urls": [ "https://origin2" ] + } + ])"); + SetAllowDevicesWithHidUsagesForUrlsPrefValue(R"( + [ + { + "usages": [ + { "usage_page": 1, "usage": 4 }, + { "usage_page": 2 } + ], + "urls": [ "https://origin3" ] + }, + { + "usages": [ + { "usage_page": 1 }, + { "usage_page": 2, "usage": 5 } + ], + "urls": [ "https://origin4" ] + } + ])"); + InitializePolicy(); + + EXPECT_EQ(2u, policy()->device_policy().size()); + EXPECT_EQ(2u, policy()->vendor_policy().size()); + EXPECT_EQ(2u, policy()->usage_policy().size()); + EXPECT_EQ(2u, policy()->usage_page_policy().size()); + EXPECT_EQ(0u, policy()->all_devices_policy().size()); + + const auto device_key1 = std::make_pair(kTestVendorId1, kTestProductId1); + ASSERT_TRUE(base::Contains(policy()->device_policy(), device_key1)); + EXPECT_THAT(policy()->device_policy().at(device_key1), + UnorderedElementsAre(kOrigin1)); + + const auto device_key2 = std::make_pair(kTestVendorId2, kTestProductId2); + ASSERT_TRUE(base::Contains(policy()->device_policy(), device_key2)); + EXPECT_THAT(policy()->device_policy().at(device_key2), + UnorderedElementsAre(kOrigin2)); + + ASSERT_TRUE(base::Contains(policy()->vendor_policy(), kTestVendorId1)); + EXPECT_THAT(policy()->vendor_policy().at(kTestVendorId1), + UnorderedElementsAre(kOrigin2)); + + ASSERT_TRUE(base::Contains(policy()->vendor_policy(), kTestVendorId2)); + EXPECT_THAT(policy()->vendor_policy().at(kTestVendorId2), + UnorderedElementsAre(kOrigin1)); + + const auto usage_key1 = std::make_pair(kTestUsagePage1, kTestUsage1); + ASSERT_TRUE(base::Contains(policy()->usage_policy(), usage_key1)); + EXPECT_THAT(policy()->usage_policy().at(usage_key1), + UnorderedElementsAre(kOrigin3)); + + const auto usage_key2 = std::make_pair(kTestUsagePage2, kTestUsage2); + ASSERT_TRUE(base::Contains(policy()->usage_policy(), usage_key2)); + EXPECT_THAT(policy()->usage_policy().at(usage_key2), + UnorderedElementsAre(kOrigin4)); + + ASSERT_TRUE(base::Contains(policy()->usage_page_policy(), kTestUsagePage1)); + EXPECT_THAT(policy()->usage_page_policy().at(kTestUsagePage1), + UnorderedElementsAre(kOrigin4)); + + ASSERT_TRUE(base::Contains(policy()->usage_page_policy(), kTestUsagePage2)); + EXPECT_THAT(policy()->usage_page_policy().at(kTestUsagePage2), + UnorderedElementsAre(kOrigin3)); + + auto device = CreateAndAddDevice(kTestVendorId1, kTestProductId1, + /*usage_page=*/0xff00, /*usage=*/1); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin3, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin4, *device)); + + device = CreateAndAddDevice(kTestVendorId1, kTestProductId2, + /*usage_page=*/0xff00, /*usage=*/1); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin3, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin4, *device)); + + device = CreateAndAddDevice(kTestVendorId2, kTestProductId2, + /*usage_page=*/0xff00, /*usage=*/1); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin3, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin4, *device)); + + device = CreateAndAddDevice(kTestVendorId2, kTestProductId1, + /*usage_page=*/0xff00, /*usage=*/1); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin3, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin4, *device)); + + device = CreateAndAddDevice(/*vendor_id=*/1, /*product_id=*/1, + kTestUsagePage1, kTestUsage1); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin4, *device)); + + device = CreateAndAddDevice(/*vendor_id=*/1, /*product_id=*/1, + kTestUsagePage1, kTestUsage2); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin3, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin4, *device)); + + device = CreateAndAddDevice(/*vendor_id=*/1, /*product_id=*/1, + kTestUsagePage2, kTestUsage2); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin4, *device)); + + device = CreateAndAddDevice(/*vendor_id=*/1, /*product_id=*/1, + kTestUsagePage2, kTestUsage1); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_TRUE(policy()->HasDevicePermission(kOrigin3, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin4, *device)); + + device = CreateAndAddDevice(/*vendor_id=*/1, /*product_id=*/1, + /*usage_page=*/0xff00, /*usage=*/1); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin1, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin2, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin3, *device)); + EXPECT_FALSE(policy()->HasDevicePermission(kOrigin4, *device)); +}
diff --git a/chrome/browser/image_editor/BUILD.gn b/chrome/browser/image_editor/BUILD.gn index a4223f0..f76103f 100644 --- a/chrome/browser/image_editor/BUILD.gn +++ b/chrome/browser/image_editor/BUILD.gn
@@ -30,6 +30,7 @@ "event_capture_mac.h", "event_capture_mac.mm", ] + deps += [ "//components/remote_cocoa/app_shim" ] } public_deps = [
diff --git a/chrome/browser/image_editor/event_capture_mac.h b/chrome/browser/image_editor/event_capture_mac.h index 02a93f6..afa32371 100644 --- a/chrome/browser/image_editor/event_capture_mac.h +++ b/chrome/browser/image_editor/event_capture_mac.h
@@ -5,35 +5,40 @@ #ifndef CHROME_BROWSER_IMAGE_EDITOR_EVENT_CAPTURE_MAC_H_ #define CHROME_BROWSER_IMAGE_EDITOR_EVENT_CAPTURE_MAC_H_ +#include "components/remote_cocoa/app_shim/mouse_capture.h" +#include "components/remote_cocoa/app_shim/mouse_capture_delegate.h" #include "ui/base/cocoa/weak_ptr_nsobject.h" #include "ui/events/event_handler.h" #include "ui/gfx/native_widget_types.h" namespace image_editor { -// A class based on ui/views/event_monitor.h, but specialized for this capture -// mode, allowing for filtering/canceling of events before they reach -// pre-target and post-target handlers. +// A class to capture mouse events on Mac and forward them to an event handler. // For other platforms we attach a pre-target handler to the main WebContents's // NativeWindow and can catch and consume events there, but some events over // the main window do not reach that approach on Mac. -class EventCaptureMac { +class EventCaptureMac : public remote_cocoa::CocoaMouseCaptureDelegate { public: EventCaptureMac(ui::EventHandler* event_handler, gfx::NativeWindow target_window); - + ~EventCaptureMac() override; EventCaptureMac(const EventCaptureMac&) = delete; EventCaptureMac& operator=(const EventCaptureMac&) = delete; - ~EventCaptureMac(); - // Allows mouse move events over the affected region requests to set a cross // cursor, using a native method. static void SetCrossCursor(); + // remote_cocoa::CocoaMouseCaptureDelegate + void PostCapturedEvent(NSEvent* event) override; + void OnMouseCaptureLost() override; + NSWindow* GetWindow() const override; + private: - id monitor_; + NSWindow* window_; + ui::EventHandler* event_handler_; ui::WeakPtrNSObjectFactory<EventCaptureMac> factory_; + std::unique_ptr<remote_cocoa::CocoaMouseCapture> mouse_capture_; }; } // namespace image_editor
diff --git a/chrome/browser/image_editor/event_capture_mac.mm b/chrome/browser/image_editor/event_capture_mac.mm index d8c64ed..60665580 100644 --- a/chrome/browser/image_editor/event_capture_mac.mm +++ b/chrome/browser/image_editor/event_capture_mac.mm
@@ -16,45 +16,33 @@ EventCaptureMac::EventCaptureMac(ui::EventHandler* event_handler, gfx::NativeWindow target_native_window) : factory_(this) { - DCHECK(event_handler); - NSWindow* target_window = target_native_window.GetNativeNSWindow(); - - // Capture a WeakPtr via NSObject. This allows the block to detect another - // event monitor for the same event deleting |this|. - WeakPtrNSObject* handle = factory_.handle(); - - auto block = ^NSEvent*(NSEvent* event) { - if (!ui::WeakPtrNSObjectFactory<EventCaptureMac>::Get(handle)) - return event; - - if (!target_window || [event window] == target_window) { - std::unique_ptr<ui::Event> ui_event = ui::EventFromNative(event); - if (!ui_event) { - return event; - } - ui::EventType type = ui_event->type(); - if (type == ui::ET_KEY_PRESSED) { - event_handler->OnKeyEvent(ui_event->AsKeyEvent()); - } - if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED || - type == ui::ET_MOUSE_PRESSED || type == ui::ET_MOUSE_RELEASED) { - event_handler->OnMouseEvent(ui_event->AsMouseEvent()); - } - // Consume the event if allowed and the corresponding EventHandler method - // requested. - if (ui_event->cancelable() && ui_event->handled()) { - return nil; - } - } - return event; - }; - - monitor_ = [NSEvent addLocalMonitorForEventsMatchingMask:NSAnyEventMask - handler:block]; + event_handler_ = event_handler; + window_ = target_native_window.GetNativeNSWindow(); + mouse_capture_ = std::make_unique<remote_cocoa::CocoaMouseCapture>(this); } -EventCaptureMac::~EventCaptureMac() { - [NSEvent removeMonitor:monitor_]; +EventCaptureMac::~EventCaptureMac() = default; + +void EventCaptureMac::PostCapturedEvent(NSEvent* event) { + std::unique_ptr<ui::Event> ui_event = ui::EventFromNative(event); + if (!ui_event) + return; + + ui::EventType type = ui_event->type(); + if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED || + type == ui::ET_MOUSE_PRESSED || type == ui::ET_MOUSE_RELEASED) { + event_handler_->OnMouseEvent(ui_event->AsMouseEvent()); + } else if (type == ui::ET_SCROLL) { + event_handler_->OnScrollEvent(ui_event->AsScrollEvent()); + } +} + +void EventCaptureMac::OnMouseCaptureLost() { + mouse_capture_.reset(); +} + +NSWindow* EventCaptureMac::GetWindow() const { + return window_; } void EventCaptureMac::SetCrossCursor() {
diff --git a/chrome/browser/image_editor/screenshot_flow.cc b/chrome/browser/image_editor/screenshot_flow.cc index 2e90a86..35574ee 100644 --- a/chrome/browser/image_editor/screenshot_flow.cc +++ b/chrome/browser/image_editor/screenshot_flow.cc
@@ -192,11 +192,11 @@ return; gfx::Point location = located_event->location(); + gfx::Rect web_contents_bounds = web_contents_->GetViewBounds(); #if BUILDFLAG(IS_MAC) // Offset |location| be relative to the WebContents widget, vs the parent // window, recomputed rather than cached in case e.g. user disables // bookmarks bar from another window. - gfx::Rect web_contents_bounds = web_contents_->GetViewBounds(); const gfx::NativeView web_contents_view = web_contents_->GetContentNativeView(); views::Widget* widget = @@ -204,12 +204,6 @@ const gfx::Rect widget_bounds = widget->GetWindowBoundsInScreen(); location.set_x(location.x() + (widget_bounds.x() - web_contents_bounds.x())); location.set_y(location.y() + (widget_bounds.y() - web_contents_bounds.y())); - // Don't capture clicks on browser ui outside the webcontents. - if (location.x() < 0 || location.y() < 0 || - location.x() > web_contents_bounds.width() || - location.y() > web_contents_bounds.height()) { - return; - } #endif switch (event->type()) { @@ -219,6 +213,15 @@ break; case ui::ET_MOUSE_PRESSED: if (event->IsLeftMouseButton()) { +#if BUILDFLAG(IS_MAC) + // Don't capture initial clicks on browser ui outside the webcontents. + if (location.x() < 0 || location.y() < 0 || + location.x() > web_contents_bounds.width() || + location.y() > web_contents_bounds.height()) { + event->SetHandled(); + break; + } +#endif // BUILDFLAG(IS_MAC) drag_start_ = location; drag_end_ = location; event->SetHandled(); @@ -234,16 +237,17 @@ case ui::ET_MOUSE_RELEASED: if (capture_mode_ == CaptureMode::SELECTION_RECTANGLE || capture_mode_ == CaptureMode::SELECTION_ELEMENT) { + AttemptRegionCapture(web_contents_bounds); event->SetHandled(); - gfx::Rect selection = gfx::BoundingRect(drag_start_, drag_end_); - drag_start_.SetPoint(0, 0); - drag_end_.SetPoint(0, 0); - if (selection.width() >= kMinimumValidSelectionEdgePixels && - selection.height() >= kMinimumValidSelectionEdgePixels) { - CompleteCapture(ScreenshotCaptureResultCode::SUCCESS, selection); - } else { - RequestRepaint(gfx::Rect()); - } + } + break; + // This event type is never called on Mac. + case ui::ET_MOUSEWHEEL: + if ((capture_mode_ == CaptureMode::SELECTION_RECTANGLE || + capture_mode_ == CaptureMode::SELECTION_ELEMENT) && + event->AsMouseWheelEvent()->y_offset() > 0) { + AttemptRegionCapture(web_contents_bounds); + event->SetHandled(); } break; default: @@ -251,6 +255,22 @@ } } +void ScreenshotFlow::OnScrollEvent(ui::ScrollEvent* event) { + // A single tap can create a scroll event, so ignore scroll starts and + // cancels but complete capture when scrolls actually occur. + if (event->type() == ui::EventType::ET_SCROLL_FLING_START || + event->type() == ui::EventType::ET_SCROLL_FLING_CANCEL) + return; + + gfx::Rect web_contents_bounds = web_contents_->GetViewBounds(); + if ((capture_mode_ == CaptureMode::SELECTION_RECTANGLE || + capture_mode_ == CaptureMode::SELECTION_ELEMENT) && + event->y_offset() > 0) { + AttemptRegionCapture(web_contents_bounds); + event->SetHandled(); + } +} + void ScreenshotFlow::CompleteCapture(ScreenshotCaptureResultCode result_code, const gfx::Rect& region) { RemoveUIOverlay(); @@ -378,6 +398,24 @@ } } +void ScreenshotFlow::AttemptRegionCapture(gfx::Rect view_bounds) { + // On Mac, it is possible for drag_end_ to end up outside of the + // Browser UI. This causes an error when completing the region + // capture. Update drag_end_ to be within the web content bounds. + drag_end_.SetToMin(gfx::Point(view_bounds.width(), view_bounds.height())); + drag_end_.SetToMax(gfx::Point(0, 0)); + + gfx::Rect selection = gfx::BoundingRect(drag_start_, drag_end_); + drag_start_.SetPoint(0, 0); + drag_end_.SetPoint(0, 0); + if (selection.width() >= kMinimumValidSelectionEdgePixels && + selection.height() >= kMinimumValidSelectionEdgePixels) { + CompleteCapture(ScreenshotCaptureResultCode::SUCCESS, selection); + } else { + RequestRepaint(gfx::Rect()); + } +} + // UnderlyingWebContentsObserver monitors the WebContents and exits screen // capture mode if a navigation occurs. class ScreenshotFlow::UnderlyingWebContentsObserver
diff --git a/chrome/browser/image_editor/screenshot_flow.h b/chrome/browser/image_editor/screenshot_flow.h index 5fd7ed4..24a3c22 100644 --- a/chrome/browser/image_editor/screenshot_flow.h +++ b/chrome/browser/image_editor/screenshot_flow.h
@@ -116,6 +116,7 @@ // ui:EventHandler: void OnKeyEvent(ui::KeyEvent* event) override; void OnMouseEvent(ui::MouseEvent* event) override; + void OnScrollEvent(ui::ScrollEvent* event) override; // ui::LayerDelegate: void OnPaintLayer(const ui::PaintContext& context) override; @@ -167,6 +168,10 @@ // Requests to set the cursor type. void SetCursor(ui::mojom::CursorType cursor_type); + // Attempts to capture the region defined by |drag_start_| and |drag_end_| + // while also making sure the points are within the web contents view bounds. + void AttemptRegionCapture(gfx::Rect view_bounds); + base::WeakPtr<ScreenshotFlow> weak_this_; // Whether we are in drag mode on this layer.
diff --git a/chrome/browser/lacros/lacros_extension_apps_publisher.cc b/chrome/browser/lacros/lacros_extension_apps_publisher.cc index d208757..923e6ec4 100644 --- a/chrome/browser/lacros/lacros_extension_apps_publisher.cc +++ b/chrome/browser/lacros/lacros_extension_apps_publisher.cc
@@ -18,6 +18,8 @@ #include "chrome/browser/ui/lacros/window_utility.h" #include "chromeos/crosapi/mojom/app_window_tracker.mojom.h" #include "chromeos/lacros/lacros_service.h" +#include "components/services/app_service/public/cpp/icon_types.h" +#include "components/services/app_service/public/cpp/intent_filter.h" #include "components/services/app_service/public/mojom/types.mojom.h" #include "extensions/browser/app_window/app_window.h" #include "extensions/browser/app_window/app_window_registry.h" @@ -37,21 +39,20 @@ return extension->is_platform_app(); } -apps::mojom::InstallReason GetInstallReason( - const extensions::Extension* extension) { +apps::InstallReason GetInstallReason(const extensions::Extension* extension) { if (extensions::Manifest::IsComponentLocation(extension->location())) - return apps::mojom::InstallReason::kSystem; + return apps::InstallReason::kSystem; if (extensions::Manifest::IsPolicyLocation(extension->location())) - return apps::mojom::InstallReason::kPolicy; + return apps::InstallReason::kPolicy; if (extension->was_installed_by_oem()) - return apps::mojom::InstallReason::kOem; + return apps::InstallReason::kOem; if (extension->was_installed_by_default()) - return apps::mojom::InstallReason::kDefault; + return apps::InstallReason::kDefault; - return apps::mojom::InstallReason::kUser; + return apps::InstallReason::kUser; } } // namespace @@ -64,7 +65,7 @@ : public extensions::ExtensionPrefsObserver, public extensions::ExtensionRegistryObserver, public extensions::AppWindowRegistry::Observer { - using Readiness = apps::mojom::Readiness; + using Readiness = apps::Readiness; public: ProfileTracker(Profile* profile, LacrosExtensionAppsPublisher* publisher) @@ -77,7 +78,7 @@ // Populate initial conditions [e.g. installed apps prior to starting // observation]. - std::vector<apps::mojom::AppPtr> apps; + std::vector<apps::AppPtr> apps; extensions::ExtensionRegistry* registry = extensions::ExtensionRegistry::Get(profile_); for (const scoped_refptr<const extensions::Extension> extension : @@ -134,8 +135,7 @@ const extensions::Extension* extension) override { if (!IsChromeApp(extension)) return; - apps::mojom::AppPtr app = MakeApp(extension, Readiness::kReady); - Publish(std::move(app)); + Publish(MakeApp(extension, Readiness::kReady)); } void OnExtensionUnloaded( @@ -168,8 +168,7 @@ case extensions::UnloadedExtensionReason::MIGRATED_TO_COMPONENT: return; } - apps::mojom::AppPtr app = MakeApp(extension, readiness); - Publish(std::move(app)); + Publish(MakeApp(extension, readiness)); } void OnExtensionInstalled(content::BrowserContext* browser_context, @@ -177,8 +176,7 @@ bool is_update) override { if (!IsChromeApp(extension)) return; - apps::mojom::AppPtr app = MakeApp(extension, Readiness::kReady); - Publish(std::move(app)); + Publish(MakeApp(extension, Readiness::kReady)); } void OnExtensionUninstalled(content::BrowserContext* browser_context, @@ -186,7 +184,7 @@ extensions::UninstallReason reason) override { if (!IsChromeApp(extension)) return; - apps::mojom::AppPtr app = + apps::AppPtr app = MakeApp(extension, reason == extensions::UNINSTALL_REASON_MIGRATED ? Readiness::kUninstalledByMigration : Readiness::kUninstalledByUser); @@ -220,14 +218,14 @@ } // Publishes a differential update to the app service. - void Publish(apps::mojom::AppPtr app) { - std::vector<apps::mojom::AppPtr> apps; + void Publish(apps::AppPtr app) { + std::vector<apps::AppPtr> apps; apps.push_back(std::move(app)); Publish(std::move(apps)); } // Publishes a vector of differential updates to the app service. - void Publish(std::vector<apps::mojom::AppPtr> apps) { + void Publish(std::vector<apps::AppPtr> apps) { publisher_->Publish(std::move(apps)); } @@ -249,13 +247,12 @@ } // Creates an AppPtr from an extension. - apps::mojom::AppPtr MakeApp(const extensions::Extension* extension, - Readiness readiness) { + apps::AppPtr MakeApp(const extensions::Extension* extension, + Readiness readiness) { DCHECK(IsChromeApp(extension)); - apps::mojom::AppPtr app = apps::mojom::App::New(); - - app->app_type = apps::mojom::AppType::kStandaloneBrowserChromeApp; - app->app_id = lacros_extension_apps_utility::MuxId(profile_, extension); + auto app = std::make_unique<apps::App>( + apps::AppType::kStandaloneBrowserChromeApp, + lacros_extension_apps_utility::MuxId(profile_, extension)); app->readiness = readiness; app->name = extension->name(); app->short_name = extension->short_name(); @@ -265,8 +262,9 @@ // This bug is tracked at https://crbug.com/1248499, but given that Chrome // Apps is deprecated, it's unclear if we'll ever get around to implementing // this functionality. - app->icon_key = apps::mojom::IconKey::New(); - app->icon_key->icon_effects = apps::IconEffects::kCrOsStandardIcon; + app->icon_key = + apps::IconKey(/*timeline=*/0, apps::IconKey::kInvalidResourceId, + apps::IconEffects::kCrOsStandardIcon); auto* prefs = extensions::ExtensionPrefs::Get(profile_); if (prefs) { @@ -278,32 +276,25 @@ } app->install_reason = GetInstallReason(extension); - app->recommendable = apps::mojom::OptionalBool::kTrue; - app->searchable = apps::mojom::OptionalBool::kTrue; - app->paused = apps::mojom::OptionalBool::kFalse; + app->recommendable = true; + app->searchable = true; + app->paused = false; - apps::mojom::OptionalBool show = ShouldShow(extension) - ? apps::mojom::OptionalBool::kTrue - : apps::mojom::OptionalBool::kFalse; + bool show = ShouldShow(extension); app->show_in_launcher = show; app->show_in_shelf = show; app->show_in_search = show; - - app->show_in_management = extension->ShouldDisplayInAppLauncher() - ? apps::mojom::OptionalBool::kTrue - : apps::mojom::OptionalBool::kFalse; + app->show_in_management = extension->ShouldDisplayInAppLauncher(); app->handles_intents = show; const extensions::ManagementPolicy* policy = extensions::ExtensionSystem::Get(profile_)->management_policy(); app->allow_uninstall = (policy->UserMayModifySettings(extension, nullptr) && - !policy->MustRemainInstalled(extension, nullptr)) - ? apps::mojom::OptionalBool::kTrue - : apps::mojom::OptionalBool::kFalse; + !policy->MustRemainInstalled(extension, nullptr)); // Add file_handlers. base::Extend(app->intent_filters, - apps_util::CreateChromeAppIntentFilters(extension)); + apps_util::CreateIntentFiltersForChromeApp(extension)); return app; } @@ -376,9 +367,14 @@ return true; } -void LacrosExtensionAppsPublisher::Publish( - std::vector<apps::mojom::AppPtr> apps) { - publisher_->OnApps(std::move(apps)); +void LacrosExtensionAppsPublisher::Publish(std::vector<apps::AppPtr> apps) { + std::vector<apps::mojom::AppPtr> mojom_apps; + for (const auto& app : apps) { + if (app) { + mojom_apps.push_back(ConvertAppToMojomApp(app)); + } + } + publisher_->OnApps(std::move(mojom_apps)); } void LacrosExtensionAppsPublisher::OnAppWindowAdded(
diff --git a/chrome/browser/lacros/lacros_extension_apps_publisher.h b/chrome/browser/lacros/lacros_extension_apps_publisher.h index 8920cf3bd..f7021f5 100644 --- a/chrome/browser/lacros/lacros_extension_apps_publisher.h +++ b/chrome/browser/lacros/lacros_extension_apps_publisher.h
@@ -14,6 +14,7 @@ #include "chrome/browser/profiles/profile_manager_observer.h" #include "chrome/browser/profiles/profile_observer.h" #include "chromeos/crosapi/mojom/app_service.mojom.h" +#include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/mojom/types.mojom-forward.h" #include "mojo/public/cpp/bindings/remote.h" @@ -58,7 +59,7 @@ protected: // Publishes differential app updates to the app_service in Ash via crosapi. // Virtual for testing. - virtual void Publish(std::vector<apps::mojom::AppPtr> apps); + virtual void Publish(std::vector<apps::AppPtr> apps); // Notifies Ash's app window tracker of an app window construction. // Virtual for testing.
diff --git a/chrome/browser/lacros/lacros_extension_apps_publisher_browsertest.cc b/chrome/browser/lacros/lacros_extension_apps_publisher_browsertest.cc index 1e44cfc..c80bd41 100644 --- a/chrome/browser/lacros/lacros_extension_apps_publisher_browsertest.cc +++ b/chrome/browser/lacros/lacros_extension_apps_publisher_browsertest.cc
@@ -20,7 +20,7 @@ namespace { -using Apps = std::vector<apps::mojom::AppPtr>; +using Apps = std::vector<apps::AppPtr>; // This fake intercepts and tracks all calls to Publish(). class LacrosExtensionAppsPublisherFake : public LacrosExtensionAppsPublisher { @@ -134,14 +134,14 @@ { Apps& apps = publisher->apps_history()[0]; ASSERT_EQ(1u, apps.size()); - ASSERT_EQ(apps[0]->readiness, apps::mojom::Readiness::kReady); + ASSERT_EQ(apps[0]->readiness, apps::Readiness::kReady); } // The last event should be an unload event. { Apps& apps = publisher->apps_history().back(); ASSERT_EQ(1u, apps.size()); - ASSERT_EQ(apps[0]->readiness, apps::mojom::Readiness::kDisabledByUser); + ASSERT_EQ(apps[0]->readiness, apps::Readiness::kDisabledByUser); } } @@ -160,14 +160,14 @@ { Apps& apps = publisher->apps_history()[0]; ASSERT_EQ(1u, apps.size()); - ASSERT_EQ(apps[0]->readiness, apps::mojom::Readiness::kReady); + ASSERT_EQ(apps[0]->readiness, apps::Readiness::kReady); } // The last event should be an uninstall event. { Apps& apps = publisher->apps_history().back(); ASSERT_EQ(1u, apps.size()); - ASSERT_EQ(apps[0]->readiness, apps::mojom::Readiness::kUninstalledByUser); + ASSERT_EQ(apps[0]->readiness, apps::Readiness::kUninstalledByUser); } }
diff --git a/chrome/browser/media/webrtc/webrtc_browsertest_base.cc b/chrome/browser/media/webrtc/webrtc_browsertest_base.cc index 706f712..39dc655 100644 --- a/chrome/browser/media/webrtc/webrtc_browsertest_base.cc +++ b/chrome/browser/media/webrtc/webrtc_browsertest_base.cc
@@ -113,11 +113,9 @@ base::ListValue::From(std::move(value)); std::vector<std::string> vector; vector.reserve(list->GetListDeprecated().size()); - for (size_t i = 0; i < list->GetListDeprecated().size(); ++i) { - base::Value* item; - EXPECT_TRUE(list->Get(i, &item)); - EXPECT_TRUE(item->is_string()); - vector.push_back(std::move(item->GetString())); + for (const base::Value& item : list->GetListDeprecated()) { + EXPECT_TRUE(item.is_string()); + vector.push_back(std::move(item.GetString())); } return vector; }
diff --git a/chrome/browser/metrics/power/power_metrics_reporter.cc b/chrome/browser/metrics/power/power_metrics_reporter.cc index 73498ee..b2747230 100644 --- a/chrome/browser/metrics/power/power_metrics_reporter.cc +++ b/chrome/browser/metrics/power/power_metrics_reporter.cc
@@ -186,16 +186,22 @@ const UsageScenarioDataStore::IntervalData& interval_data, const ProcessMonitor::Metrics& aggregated_process_metrics, base::TimeDelta interval_duration, - BatteryDischarge battery_discharge) { + BatteryDischarge battery_discharge +#if BUILDFLAG(IS_MAC) + , + const absl::optional<CoalitionResourceUsageRate>& + coalition_resource_usage_rate +#endif +) { const std::vector<const char*> suffixes = GetSuffixes(interval_data); ReportAggregatedProcessMetricsHistograms(aggregated_process_metrics, suffixes); ReportBatteryHistograms(interval_duration, battery_discharge, suffixes); #if BUILDFLAG(IS_MAC) - if (aggregated_process_metrics.coalition_data.has_value()) { - ReportResourceCoalitionHistograms( - aggregated_process_metrics.coalition_data.value(), suffixes); + if (coalition_resource_usage_rate.has_value()) { + ReportResourceCoalitionHistograms(coalition_resource_usage_rate.value(), + suffixes); } #endif } @@ -263,19 +269,6 @@ auto battery_discharge = GetBatteryDischargeDuringInterval(battery_state, interval_duration); - ReportUKMsAndHistograms(aggregated_process_metrics, interval_duration, - battery_discharge); - - if (on_battery_sampled_for_testing_) - std::move(on_battery_sampled_for_testing_).Run(); -} - -void PowerMetricsReporter::ReportUKMsAndHistograms( - const ProcessMonitor::Metrics& aggregated_process_metrics, - base::TimeDelta interval_duration, - BatteryDischarge battery_discharge) const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(data_store_.MaybeValid()); UsageScenarioDataStore::IntervalData interval_data = data_store_->ResetIntervalData(); @@ -304,7 +297,15 @@ battery_discharge, main_screen_brightness); ReportHistograms(interval_data, aggregated_process_metrics, interval_duration, - battery_discharge); + battery_discharge +#if BUILDFLAG(IS_MAC) + , + aggregated_process_metrics.coalition_data +#endif // BUILDFLAG(IS_MAC) + ); + + if (on_battery_sampled_for_testing_) + std::move(on_battery_sampled_for_testing_).Run(); } // static
diff --git a/chrome/browser/metrics/power/power_metrics_reporter.h b/chrome/browser/metrics/power/power_metrics_reporter.h index c9d802f..56d5001 100644 --- a/chrome/browser/metrics/power/power_metrics_reporter.h +++ b/chrome/browser/metrics/power/power_metrics_reporter.h
@@ -30,6 +30,9 @@ : public performance_monitor::ProcessMonitor::Observer { public: using ProcessMonitor = performance_monitor::ProcessMonitor; +#if BUILDFLAG(IS_MAC) + using CoalitionResourceUsageRate = power_metrics::CoalitionResourceUsageRate; +#endif // BUILDFLAG(IS_MAC) // |data_store| will be queried at regular interval to report the metrics, it // needs to outlive this class. @@ -83,13 +86,19 @@ absl::optional<int64_t> rate; }; - // Report battery and CPU metrics to generic histograms and histograms with a - // scenario suffix derived from |interval_data|. + // Report metrics to generic histograms and histograms with a scenario suffix + // derived from |interval_data|. static void ReportHistograms( const UsageScenarioDataStore::IntervalData& interval_data, const ProcessMonitor::Metrics& aggregated_process_metrics, base::TimeDelta interval_duration, - BatteryDischarge battery_discharge); + BatteryDischarge battery_discharge +#if BUILDFLAG(IS_MAC) + , + const absl::optional<CoalitionResourceUsageRate>& + coalition_resource_usage_rate +#endif + ); // Report battery metrics to histograms with |suffixes|. static void ReportBatteryHistograms(base::TimeDelta interval_duration, @@ -127,11 +136,6 @@ BatteryDischarge battery_discharge, absl::optional<int64_t> main_screen_brightness) const; - void ReportUKMsAndHistograms( - const ProcessMonitor::Metrics& aggregated_process_metrics, - base::TimeDelta interval_duration, - BatteryDischarge battery_discharge) const; - // Computes and returns the battery discharge mode and rate during the // interval, and reset |battery_state_| to the current state. If the discharge // rate isn't valid, the returned value is nullopt and the reason is indicated
diff --git a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc index 4cfbd36..737a36cf 100644 --- a/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc +++ b/chrome/browser/metrics/power/power_metrics_reporter_unittest.cc
@@ -52,22 +52,45 @@ #if BUILDFLAG(IS_MAC) power_metrics::CoalitionResourceUsageRate GetFakeResourceUsageRate() { power_metrics::CoalitionResourceUsageRate rate; - rate.cpu_time_per_second = 0.1; - rate.interrupt_wakeups_per_second = 0.3; - rate.platform_idle_wakeups_per_second = 2; - rate.bytesread_per_second = 10; - rate.byteswritten_per_second = 0.1; - rate.gpu_time_per_second = 0.8; - rate.energy_impact_per_second = 3.0; - rate.power_nw = 1000; + rate.cpu_time_per_second = 0.5; + rate.interrupt_wakeups_per_second = 10; + rate.platform_idle_wakeups_per_second = 11; + rate.bytesread_per_second = 12; + rate.byteswritten_per_second = 13; + rate.gpu_time_per_second = 0.6; + rate.energy_impact_per_second = 15; + rate.power_nw = 1000000; for (int i = 0; i < COALITION_NUM_THREAD_QOS_TYPES; ++i) - rate.qos_time_per_second[i] = i * 0.1; + rate.qos_time_per_second[i] = 0.1 * i; return rate; } #endif // BUILDFLAG(IS_MAC) +struct HistogramSampleExpectation { + std::string histogram_name_prefix; + base::Histogram::Sample sample; +}; + +// For each histogram named after the combination of prefixes from +// `expectations` and suffixes from `suffixes`, verifies that there is a unique +// sample `expectation.sample`. +void ExpectHistogramSamples( + base::HistogramTester* histogram_tester, + const std::vector<const char*>& suffixes, + const std::vector<HistogramSampleExpectation>& expectations) { + for (const char* suffix : suffixes) { + for (const auto& expectation : expectations) { + std::string histogram_name = + base::StrCat({expectation.histogram_name_prefix, suffix}); + SCOPED_TRACE(histogram_name); + histogram_tester->ExpectUniqueSample(histogram_name, expectation.sample, + 1); + } + } +} + using UkmEntry = ukm::builders::PowerUsageScenariosIntervalData; class PowerMetricsReporterAccess : public PowerMetricsReporter { @@ -569,25 +592,29 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2.ZeroWindow", - 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode.ZeroWindow", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.ZeroWindow", 500, 1); + const std::vector<const char*> suffixes({"", ".ZeroWindow"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the - // PerformanceMonitor.* histograms is recorded correctly. + // PerformanceMonitor.* and ResourceCoalition.* histograms is recorded + // correctly. } TEST_F(PowerMetricsReporterUnitTest, @@ -607,24 +634,25 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeRate2.AllTabsHidden_VideoCapture", 2500, 1); - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeMode.AllTabsHidden_VideoCapture", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.AllTabsHidden_VideoCapture", 500, - 1); + const std::vector<const char*> suffixes({"", ".AllTabsHidden_VideoCapture"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the // PerformanceMonitor.* histograms is recorded correctly. @@ -646,23 +674,25 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeRate2.AllTabsHidden_Audio", 2500, 1); - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeMode.AllTabsHidden_Audio", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.AllTabsHidden_Audio", 500, 1); + const std::vector<const char*> suffixes({"", ".AllTabsHidden_Audio"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the // PerformanceMonitor.* histograms is recorded correctly. @@ -685,29 +715,30 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeRate2.AllTabsHidden_NoVideoCaptureOrAudio", 2500, - 1); - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeMode.AllTabsHidden_NoVideoCaptureOrAudio", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.AllTabsHidden_" - "NoVideoCaptureOrAudio", - 500, 1); + const std::vector<const char*> suffixes( + {"", ".AllTabsHidden_NoVideoCaptureOrAudio"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the - // PerformanceMonitor.* histograms is recorded correctly. + // PerformanceMonitor.* and ResourceCoalition.* histograms is recorded + // correctly. } TEST_F(PowerMetricsReporterUnitTest, SuffixedHistograms_VideoCapture) { @@ -726,26 +757,29 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeRate2.VideoCapture", 2500, 1); - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeMode.VideoCapture", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.VideoCapture", 500, 1); + const std::vector<const char*> suffixes({"", ".VideoCapture"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the - // PerformanceMonitor.* histograms is recorded correctly. + // PerformanceMonitor.* and ResourceCoalition.* histograms is recorded + // correctly. } TEST_F(PowerMetricsReporterUnitTest, SuffixedHistograms_FullscreenVideo) { @@ -764,26 +798,29 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeRate2.FullscreenVideo", 2500, 1); - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeMode.FullscreenVideo", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.FullscreenVideo", 500, 1); + const std::vector<const char*> suffixes({"", ".FullscreenVideo"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the - // PerformanceMonitor.* histograms is recorded correctly. + // PerformanceMonitor.* and ResourceCoalition.* histograms is recorded + // correctly. } TEST_F(PowerMetricsReporterUnitTest, @@ -803,27 +840,29 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeRate2.EmbeddedVideo_NoNavigation", 2500, 1); - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeMode.EmbeddedVideo_NoNavigation", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.EmbeddedVideo_NoNavigation", 500, - 1); + const std::vector<const char*> suffixes({"", ".EmbeddedVideo_NoNavigation"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the - // PerformanceMonitor.* histograms is recorded correctly. + // PerformanceMonitor.* and ResourceCoalition.* histograms is recorded + // correctly. } TEST_F(PowerMetricsReporterUnitTest, @@ -843,27 +882,30 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeRate2.EmbeddedVideo_WithNavigation", 2500, 1); - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeMode.EmbeddedVideo_WithNavigation", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.EmbeddedVideo_WithNavigation", 500, - 1); + const std::vector<const char*> suffixes( + {"", ".EmbeddedVideo_WithNavigation"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the - // PerformanceMonitor.* histograms is recorded correctly. + // PerformanceMonitor.* and ResourceCoalition.* histograms is recorded + // correctly. } TEST_F(PowerMetricsReporterUnitTest, SuffixedHistograms_Audio) { @@ -882,25 +924,29 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2.Audio", - 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode.Audio", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.Audio", 500, 1); + const std::vector<const char*> suffixes({"", ".Audio"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the - // PerformanceMonitor.* histograms is recorded correctly. + // PerformanceMonitor.* and ResourceCoalition.* histograms is recorded + // correctly. } TEST_F(PowerMetricsReporterUnitTest, SuffixedHistograms_Navigation) { @@ -919,25 +965,29 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2.Navigation", - 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode.Navigation", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.Navigation", 500, 1); + const std::vector<const char*> suffixes({"", ".Navigation"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the - // PerformanceMonitor.* histograms is recorded correctly. + // PerformanceMonitor.* and ResourceCoalition.* histograms is recorded + // correctly. } TEST_F(PowerMetricsReporterUnitTest, SuffixedHistograms_Interaction) { @@ -955,25 +1005,29 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample( - "Power.BatteryDischargeRate2.Interaction", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode.Interaction", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.Interaction", 500, 1); + const std::vector<const char*> suffixes({"", ".Interaction"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the - // PerformanceMonitor.* histograms is recorded correctly. + // PerformanceMonitor.* and ResourceCoalition.* histograms is recorded + // correctly. } TEST_F(PowerMetricsReporterUnitTest, SuffixedHistograms_Passive) { @@ -991,25 +1045,29 @@ PowerMetricsReporterAccess::ReportHistograms( interval_data, GetFakeProcessMetrics(), kExpectedMetricsCollectionInterval, - BatteryDischarge{BatteryDischargeMode::kDischarging, 2500}); + BatteryDischarge { BatteryDischargeMode::kDischarging, 2500 } +#if BUILDFLAG(IS_MAC) + , + GetFakeResourceUsageRate() +#endif // BUILDFLAG(IS_MAC) + ); - // Non-suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2", 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample("PerformanceMonitor.AverageCPU2.Total", - 500, 1); - - // Suffixed histograms. - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeRate2.Passive", - 2500, 1); - histogram_tester_.ExpectUniqueSample("Power.BatteryDischargeMode.Passive", - BatteryDischargeMode::kDischarging, 1); - histogram_tester_.ExpectUniqueSample( - "PerformanceMonitor.AverageCPU2.Total.Passive", 500, 1); + const std::vector<const char*> suffixes({"", ".Passive"}); + ExpectHistogramSamples(&histogram_tester_, suffixes, { + {"Power.BatteryDischargeRate2", 2500}, + {"Power.BatteryDischargeMode", static_cast<base::Histogram::Sample>( + BatteryDischargeMode::kDischarging)}, + { + "PerformanceMonitor.AverageCPU2.Total", 500 + } +#if BUILDFLAG(IS_MAC) + , { "PerformanceMonitor.ResourceCoalition.CPUTime2", 5000 } +#endif // BUILDFLAG(IS_MAC) + }); // Note: For simplicity, this test only verifies that one of the - // PerformanceMonitor.* histograms is recorded correctly. + // PerformanceMonitor.* and ResourceCoalition.* histograms is recorded + // correctly. } TEST_F(PowerMetricsReporterUnitTest, BatteryDischargeCaptureIsTooEarly) { @@ -1205,91 +1263,43 @@ #if BUILDFLAG(IS_MAC) TEST_F(PowerMetricsReporterUnitTest, ReportResourceCoalitionHistograms) { base::HistogramTester histogram_tester; - power_metrics::CoalitionResourceUsageRate rate = GetFakeResourceUsageRate(); - std::vector<const char*> suffixes = {"", ".Foo", ".Bar"}; - PowerMetricsReporterAccess::ReportResourceCoalitionHistograms(rate, suffixes); + const std::vector<const char*> suffixes = {"", ".Foo", ".Bar"}; + PowerMetricsReporterAccess::ReportResourceCoalitionHistograms( + GetFakeResourceUsageRate(), suffixes); - for (const char* scenario_suffix : suffixes) { - // These histograms reports the CPU/GPU times as a percentage of time with a - // permyriad granularity, 10% (0.1) will be represented as 1000. - histogram_tester.ExpectUniqueSample( - base::StrCat( - {"PerformanceMonitor.ResourceCoalition.CPUTime2", scenario_suffix}), - rate.cpu_time_per_second * 10000, 1); - histogram_tester.ExpectUniqueSample( - base::StrCat( - {"PerformanceMonitor.ResourceCoalition.GPUTime2", scenario_suffix}), - rate.gpu_time_per_second * 10000, 1); - - // These histograms report counts with a millievent/second granularity. - histogram_tester.ExpectUniqueSample( - base::StrCat( - {"PerformanceMonitor.ResourceCoalition.InterruptWakeupsPerSecond", - scenario_suffix}), - rate.interrupt_wakeups_per_second * 1000, 1); - histogram_tester.ExpectUniqueSample( - base::StrCat({"PerformanceMonitor.ResourceCoalition." - "PlatformIdleWakeupsPerSecond", - scenario_suffix}), - rate.platform_idle_wakeups_per_second * 1000, 1); - histogram_tester.ExpectUniqueSample( - base::StrCat({"PerformanceMonitor.ResourceCoalition.BytesReadPerSecond", - scenario_suffix}), - rate.bytesread_per_second * 1000, 1); - histogram_tester.ExpectUniqueSample( - base::StrCat( - {"PerformanceMonitor.ResourceCoalition.BytesWrittenPerSecond", - scenario_suffix}), - rate.byteswritten_per_second * 1000, 1); - // EI is reported in centi-EI so the data needs to be multiplied by 100.0. - histogram_tester.ExpectUniqueSample( - base::StrCat({"PerformanceMonitor.ResourceCoalition.EnergyImpact", - scenario_suffix}), - rate.energy_impact_per_second.value() * 100.0, 1); - - // Power is reported in milliwatts (mj/s), the data is in nj/s so it has to - // be divided by 1000000. - histogram_tester.ExpectUniqueSample( - base::StrCat( - {"PerformanceMonitor.ResourceCoalition.Power", scenario_suffix}), - rate.power_nw / 1000000, 1); - - // The QoS histograms also reports the CPU times as a percentage of time - // with a permyriad granularity. - histogram_tester.ExpectUniqueSample( - base::StrCat({"PerformanceMonitor.ResourceCoalition.QoSLevel.Default", - scenario_suffix}), - rate.qos_time_per_second[0] * 10000, 1); - histogram_tester.ExpectUniqueSample( - base::StrCat( - {"PerformanceMonitor.ResourceCoalition.QoSLevel.Maintenance", - scenario_suffix}), - rate.qos_time_per_second[1] * 10000, 1); - histogram_tester.ExpectUniqueSample( - base::StrCat( - {"PerformanceMonitor.ResourceCoalition.QoSLevel.Background", - scenario_suffix}), - rate.qos_time_per_second[2] * 10000, 1); - histogram_tester.ExpectUniqueSample( - base::StrCat({"PerformanceMonitor.ResourceCoalition.QoSLevel.Utility", - scenario_suffix}), - rate.qos_time_per_second[3] * 10000, 1); - histogram_tester.ExpectUniqueSample( - base::StrCat({"PerformanceMonitor.ResourceCoalition.QoSLevel.Legacy", - scenario_suffix}), - rate.qos_time_per_second[4] * 10000, 1); - histogram_tester.ExpectUniqueSample( - base::StrCat( - {"PerformanceMonitor.ResourceCoalition.QoSLevel.UserInitiated", - scenario_suffix}), - rate.qos_time_per_second[5] * 10000, 1); - histogram_tester.ExpectUniqueSample( - base::StrCat( - {"PerformanceMonitor.ResourceCoalition.QoSLevel.UserInteractive", - scenario_suffix}), - rate.qos_time_per_second[6] * 10000, 1); - } + ExpectHistogramSamples( + &histogram_tester, suffixes, + {// These histograms reports the CPU/GPU times as a percentage of + // time with a permyriad granularity, 10% (0.1) will be represented + // as 1000. + {"PerformanceMonitor.ResourceCoalition.CPUTime2", 5000}, + {"PerformanceMonitor.ResourceCoalition.GPUTime2", 6000}, + // These histograms report counts with a millievent/second + // granularity. + {"PerformanceMonitor.ResourceCoalition.InterruptWakeupsPerSecond", + 10000}, + {"PerformanceMonitor.ResourceCoalition." + "PlatformIdleWakeupsPerSecond", + 11000}, + {"PerformanceMonitor.ResourceCoalition.BytesReadPerSecond", 12000}, + {"PerformanceMonitor.ResourceCoalition.BytesWrittenPerSecond", 13000}, + // EI is reported in centi-EI so the data needs to be multiplied by + // 100.0. + {"PerformanceMonitor.ResourceCoalition.EnergyImpact", 1500}, + // Power is reported in milliwatts (mj/s), the data is in nj/s so it + // has to be divided by 1000000. + {"PerformanceMonitor.ResourceCoalition.Power", 1}, + // The QoS histograms also reports the CPU times as a percentage of + // time with a permyriad granularity. + {"PerformanceMonitor.ResourceCoalition.QoSLevel.Default", 0}, + {"PerformanceMonitor.ResourceCoalition.QoSLevel.Maintenance", 1000}, + {"PerformanceMonitor.ResourceCoalition.QoSLevel.Background", 2000}, + {"PerformanceMonitor.ResourceCoalition.QoSLevel.Utility", 3000}, + {"PerformanceMonitor.ResourceCoalition.QoSLevel.Legacy", 4000}, + {"PerformanceMonitor.ResourceCoalition.QoSLevel.UserInitiated", 5000}, + {"PerformanceMonitor.ResourceCoalition.QoSLevel.UserInteractive", + 6000}}); } // Verify that no energy impact histogram is reported when
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.cc index d1ff19d..c2cc52e 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.cc +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.cc
@@ -161,7 +161,8 @@ return NearbyShareDecryptedPublicCertificate( not_before, not_after, std::move(secret_key), std::move(public_key), - std::move(id), std::move(unencrypted_metadata)); + std::move(id), std::move(unencrypted_metadata), + public_certificate.for_self_share()); } NearbyShareDecryptedPublicCertificate::NearbyShareDecryptedPublicCertificate( @@ -170,13 +171,15 @@ std::unique_ptr<crypto::SymmetricKey> secret_key, std::vector<uint8_t> public_key, std::vector<uint8_t> id, - nearbyshare::proto::EncryptedMetadata unencrypted_metadata) + nearbyshare::proto::EncryptedMetadata unencrypted_metadata, + bool for_self_share) : not_before_(not_before), not_after_(not_after), secret_key_(std::move(secret_key)), public_key_(std::move(public_key)), id_(std::move(id)), - unencrypted_metadata_(std::move(unencrypted_metadata)) {} + unencrypted_metadata_(std::move(unencrypted_metadata)), + for_self_share_(for_self_share) {} NearbyShareDecryptedPublicCertificate::NearbyShareDecryptedPublicCertificate( const NearbyShareDecryptedPublicCertificate& other) {
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h index fc196fa..8f3e4954 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate.h
@@ -49,6 +49,7 @@ const nearbyshare::proto::EncryptedMetadata& unencrypted_metadata() const { return unencrypted_metadata_; } + bool for_self_share() const { return for_self_share_; } // Verifies the |signature| of the signed |payload| using |public_key_|. // Returns true if verification was successful. @@ -68,7 +69,8 @@ std::unique_ptr<crypto::SymmetricKey> secret_key, std::vector<uint8_t> public_key, std::vector<uint8_t> id, - nearbyshare::proto::EncryptedMetadata unencrypted_metadata); + nearbyshare::proto::EncryptedMetadata unencrypted_metadata, + bool for_self_share); // The begin/end times of the certificate's validity period. To avoid issues // with clock skew, these time might be offset compared to the corresponding @@ -90,6 +92,10 @@ // Unencrypted device metadata. The proto name is misleading; it holds data // that was previously serialized and encrypted. nearbyshare::proto::EncryptedMetadata unencrypted_metadata_; + + // Indicates if this public certificate is from another device owned by the + // same user. + bool for_self_share_ = false; }; #endif // CHROME_BROWSER_NEARBY_SHARING_CERTIFICATES_NEARBY_SHARE_DECRYPTED_PUBLIC_CERTIFICATE_H_
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate_unittest.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate_unittest.cc index a039b939e..a66a164 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate_unittest.cc +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_decrypted_public_certificate_unittest.cc
@@ -25,6 +25,7 @@ TEST(NearbyShareDecryptedPublicCertificateTest, Decrypt) { nearbyshare::proto::PublicCertificate proto_cert = GetNearbyShareTestPublicCertificate(kTestPublicCertificateVisibility); + proto_cert.set_for_self_share(true); absl::optional<NearbyShareDecryptedPublicCertificate> cert = NearbyShareDecryptedPublicCertificate::DecryptPublicCertificate( @@ -39,6 +40,7 @@ cert->id()); EXPECT_EQ(GetNearbyShareTestMetadata().SerializeAsString(), cert->unencrypted_metadata().SerializeAsString()); + EXPECT_EQ(proto_cert.for_self_share(), cert->for_self_share()); } TEST(NearbyShareDecryptedPublicCertificateTest, Decrypt_IncorrectKeyFailure) {
diff --git a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc index 9e3cf2d8d..ebedcfb2 100644 --- a/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc +++ b/chrome/browser/nearby_sharing/certificates/nearby_share_private_certificate.cc
@@ -294,6 +294,9 @@ std::string(metadata_encryption_key_tag->begin(), metadata_encryption_key_tag->end())); + // Note: The |for_self_share| field is not set by clients but is set by the + // server for all downloaded public certificates. + return public_certificate; }
diff --git a/chrome/browser/nearby_sharing/logging/proto_to_dictionary_conversion.cc b/chrome/browser/nearby_sharing/logging/proto_to_dictionary_conversion.cc index 07581202..5bf781f 100644 --- a/chrome/browser/nearby_sharing/logging/proto_to_dictionary_conversion.cc +++ b/chrome/browser/nearby_sharing/logging/proto_to_dictionary_conversion.cc
@@ -78,6 +78,7 @@ dict.SetStringKey( "metadata_encryption_key_tag", TruncateString(Encode(certificate.metadata_encryption_key_tag()))); + dict.SetBoolKey("for_self_share", certificate.for_self_share()); return dict; }
diff --git a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc index a17f1f9..94b56d4 100644 --- a/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc +++ b/chrome/browser/nearby_sharing/nearby_share_metrics_logger.cc
@@ -302,12 +302,13 @@ switch (*last_upgraded_medium) { case location::nearby::connections::mojom::Medium::kWebRtc: return ".WebRtcUpgrade"; + case location::nearby::connections::mojom::Medium::kWifiLan: + return ".WifiLanUpgrade"; case location::nearby::connections::mojom::Medium::kUnknown: case location::nearby::connections::mojom::Medium::kMdns: case location::nearby::connections::mojom::Medium::kBluetooth: case location::nearby::connections::mojom::Medium::kWifiHotspot: case location::nearby::connections::mojom::Medium::kBle: - case location::nearby::connections::mojom::Medium::kWifiLan: case location::nearby::connections::mojom::Medium::kWifiAware: case location::nearby::connections::mojom::Medium::kNfc: case location::nearby::connections::mojom::Medium::kWifiDirect:
diff --git a/chrome/browser/nearby_sharing/proto/rpc_resources.proto b/chrome/browser/nearby_sharing/proto/rpc_resources.proto index 07ba40f..116e8e4b 100644 --- a/chrome/browser/nearby_sharing/proto/rpc_resources.proto +++ b/chrome/browser/nearby_sharing/proto/rpc_resources.proto
@@ -56,6 +56,11 @@ // The tag for verifying metadata_encryption_key. bytes metadata_encryption_key_tag = 9; + + // Indicates if this public certificate corresponds to a device owned by the + // current user. This is not set by the clients but is set by the server for + // all public certificates (regardless of certificate type). + bool for_self_share = 10; } // A member of a contact list. This is not inlined on the recommendation of
diff --git a/chrome/browser/optimization_guide/prediction/prediction_manager.cc b/chrome/browser/optimization_guide/prediction/prediction_manager.cc index 0f1e19e5..f93bda1 100644 --- a/chrome/browser/optimization_guide/prediction/prediction_manager.cc +++ b/chrome/browser/optimization_guide/prediction/prediction_manager.cc
@@ -386,7 +386,7 @@ if (features::IsModelDownloadingEnabled()) { // There should only be one supported model engine version at a time. base_model_info.add_supported_model_engine_versions( - proto::MODEL_ENGINE_VERSION_TFLITE_2_9); + proto::MODEL_ENGINE_VERSION_TFLITE_2_9_0_1); // This histogram is used for integration tests. Do not remove. // Update this to be 10000 if/when we exceed 100 model engine versions. LOCAL_HISTOGRAM_COUNTS_100(
diff --git a/chrome/browser/pdf/pdf_extension_test.cc b/chrome/browser/pdf/pdf_extension_test.cc index 67b0807..413626f 100644 --- a/chrome/browser/pdf/pdf_extension_test.cc +++ b/chrome/browser/pdf/pdf_extension_test.cc
@@ -3783,7 +3783,7 @@ // Set focus on last toolbar element (zoom-out-button). ASSERT_TRUE( content::ExecuteScript(guest_contents, - R"(viewer.shadowRoot.querySelector('#zoom-toolbar') + R"(viewer.shadowRoot.querySelector('#zoomToolbar') .$['zoom-out-button'] .$$('cr-icon-button') .focus();)")); @@ -3795,7 +3795,7 @@ window.domAutomationController.send('plugin'); }); - const button = viewer.shadowRoot.querySelector('#zoom-toolbar') + const button = viewer.shadowRoot.querySelector('#zoomToolbar') .$['zoom-out-button'] .$$('cr-icon-button'); button.addEventListener('focus', () => {
diff --git a/chrome/browser/plugins/plugin_finder_unittest.cc b/chrome/browser/plugins/plugin_finder_unittest.cc index e63f0a65..0337ca5 100644 --- a/chrome/browser/plugins/plugin_finder_unittest.cc +++ b/chrome/browser/plugins/plugin_finder_unittest.cc
@@ -25,18 +25,17 @@ !plugin_it.IsAtEnd(); plugin_it.Advance()) { const base::DictionaryValue* plugin = NULL; ASSERT_TRUE(plugin_it.value().GetAsDictionary(&plugin)); - std::string dummy_str; - if (plugin->HasKey("lang")) - EXPECT_TRUE(plugin->GetString("lang", &dummy_str)); - if (plugin->HasKey("url")) - EXPECT_TRUE(plugin->GetString("url", &dummy_str)); - EXPECT_TRUE(plugin->GetString("name", &dummy_str)); - if (plugin->HasKey("help_url")) - EXPECT_TRUE(plugin->GetString("help_url", &dummy_str)); - if (plugin->HasKey("displayurl")) { + if (plugin->FindKey("lang")) + EXPECT_TRUE(plugin->FindStringKey("lang")); + if (plugin->FindKey("url")) + EXPECT_TRUE(plugin->FindStringKey("url")); + EXPECT_TRUE(plugin->FindStringKey("name")); + if (plugin->FindKey("help_url")) + EXPECT_TRUE(plugin->FindStringKey("help_url")); + if (plugin->FindKey("displayurl")) { EXPECT_THAT(plugin->FindBoolKey("displayurl"), Optional(true)); } - if (plugin->HasKey("requires_authorization")) + if (plugin->FindKey("requires_authorization")) EXPECT_TRUE(plugin->FindBoolKey("requires_authorization").has_value()); const base::ListValue* mime_types = NULL; if (plugin->GetList("mime_types", &mime_types)) { @@ -59,13 +58,13 @@ for (const auto& version_value : versions->GetListDeprecated()) { const base::DictionaryValue* version_dict = nullptr; ASSERT_TRUE(version_value.GetAsDictionary(&version_dict)); - EXPECT_TRUE(version_dict->GetString("version", &dummy_str)); - std::string status_str; - EXPECT_TRUE(version_dict->GetString("status", &status_str)); + EXPECT_TRUE(version_dict->FindStringKey("version")); + const std::string* status_str = version_dict->FindStringKey("status"); + ASSERT_TRUE(status_str); PluginMetadata::SecurityStatus status = PluginMetadata::SECURITY_STATUS_UP_TO_DATE; - EXPECT_TRUE(PluginMetadata::ParseSecurityStatus(status_str, &status)) - << "Invalid security status \"" << status_str << "\""; + EXPECT_TRUE(PluginMetadata::ParseSecurityStatus(*status_str, &status)) + << "Invalid security status \"" << *status_str << "\""; } } }
diff --git a/chrome/browser/prefetch/search_prefetch/base_search_prefetch_request.cc b/chrome/browser/prefetch/search_prefetch/base_search_prefetch_request.cc index 76e16d45..01c1805 100644 --- a/chrome/browser/prefetch/search_prefetch/base_search_prefetch_request.cc +++ b/chrome/browser/prefetch/search_prefetch/base_search_prefetch_request.cc
@@ -82,17 +82,29 @@ bool cancelled_or_paused_ = false; }; +bool DoesHeaderContainClientHint( + const net::HttpRequestHeaders& headers, + const network::mojom::WebClientHintsType hint) { + const std::string& header = network::GetClientHintToNameMap().at(hint); + std::string value; + return headers.GetHeader(header, &value) && value == "?1"; +} + // Computes the user agent value that should set for the User-Agent header. std::string GetUserAgentValue(const net::HttpRequestHeaders& headers) { - // If Sec-CH-UA-Reduced is set on the headers, it means that the token for the - // UserAgentReduction Origin Trial has been validated and we should send a - // reduced UA string on the request. - std::string header = network::GetClientHintToNameMap().at( - network::mojom::WebClientHintsType::kUAReduced); - std::string value; - return headers.GetHeader(header, &value) && value == "?1" - ? embedder_support::GetReducedUserAgent() - : embedder_support::GetUserAgent(); + // If Sec-CH-UA-Full is set on the headers, it means that the token for the + // SendFullUserAgentAfterReduction Origin Trial has been validated and we + // should send a reduced UA string on the request. Then check if + // Sec-CH-UA-Reduced is set on the headers, it means that the token for the + // UserAgentReduction Origin Trial has been validated and we + // should send a reduced UA string on the request. + const bool ua_reduced = DoesHeaderContainClientHint( + headers, network::mojom::WebClientHintsType::kUAReduced); + const bool ua_full = DoesHeaderContainClientHint( + headers, network::mojom::WebClientHintsType::kFullUserAgent); + return ua_full ? embedder_support::GetUserAgent() + : (ua_reduced ? embedder_support::GetReducedUserAgent() + : embedder_support::GetUserAgent()); } } // namespace
diff --git a/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc b/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc index 420444d..a27a158 100644 --- a/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc +++ b/chrome/browser/prefs/chrome_command_line_pref_store_unittest.cc
@@ -73,9 +73,8 @@ const base::Value* actual = nullptr; EXPECT_TRUE(store->GetValue(language::prefs::kApplicationLocale, &actual)); - std::string result; - EXPECT_TRUE(actual->GetAsString(&result)); - EXPECT_EQ("hi-MOM", result); + ASSERT_TRUE(actual->is_string()); + EXPECT_EQ("hi-MOM", actual->GetString()); } // Tests a simple boolean pref on the command line.
diff --git a/chrome/browser/prefs/profile_pref_store_manager_unittest.cc b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc index f1a11d1..683bf1e4 100644 --- a/chrome/browser/prefs/profile_pref_store_manager_unittest.cc +++ b/chrome/browser/prefs/profile_pref_store_manager_unittest.cc
@@ -308,13 +308,12 @@ void ExpectStringValueEquals(const std::string& name, const std::string& expected) { const base::Value* value = NULL; - std::string as_string; if (!pref_store_->GetValue(name, &value)) { ADD_FAILURE() << name << " is not a defined value."; - } else if (!value->GetAsString(&as_string)) { + } else if (!value->is_string()) { ADD_FAILURE() << name << " could not be coerced to a string."; } else { - EXPECT_EQ(expected, as_string); + EXPECT_EQ(expected, value->GetString()); } }
diff --git a/chrome/browser/printing/print_browsertest.cc b/chrome/browser/printing/print_browsertest.cc index 4f4e006..1bc052b 100644 --- a/chrome/browser/printing/print_browsertest.cc +++ b/chrome/browser/printing/print_browsertest.cc
@@ -1622,7 +1622,7 @@ .$['previewArea'] .shadowRoot.querySelector('iframe') .contentDocument.querySelector('pdf-viewer-pp') - .shadowRoot.querySelector('#zoom-toolbar') + .shadowRoot.querySelector('#zoomToolbar') .$['zoom-out-button']; button.addEventListener('focus', (e) => { window.domAutomationController.send(e.target.id);
diff --git a/chrome/browser/resources/BUILD.gn b/chrome/browser/resources/BUILD.gn index 6ca9ce2..8a28c89 100644 --- a/chrome/browser/resources/BUILD.gn +++ b/chrome/browser/resources/BUILD.gn
@@ -31,6 +31,7 @@ "commander:resources", "download_shelf:resources", "downloads:resources", + "feed:resources", "feedback_webui:resources", "gaia_auth_host:resources", "history:resources",
diff --git a/chrome/browser/resources/chromeos/crostini_upgrader/app.js b/chrome/browser/resources/chromeos/crostini_upgrader/app.js index 24522b7..9c53fea 100644 --- a/chrome/browser/resources/chromeos/crostini_upgrader/app.js +++ b/chrome/browser/resources/chromeos/crostini_upgrader/app.js
@@ -21,14 +21,15 @@ const State = { PROMPT: 'prompt', BACKUP: 'backup', + BACKUP_ERROR: 'backupError', BACKUP_SUCCEEDED: 'backupSucceeded', PRECHECKS_FAILED: 'prechecksFailed', UPGRADING: 'upgrading', UPGRADE_ERROR: 'upgrade_error', OFFER_RESTORE: 'offerRestore', RESTORE: 'restore', + RESTORE_ERROR: 'restoreError', RESTORE_SUCCEEDED: 'restoreSucceeded', - ERROR: 'error', CANCELING: 'canceling', SUCCEEDED: 'succeeded', }; @@ -149,7 +150,7 @@ }), callbackRouter.onBackupFailed.addListener(() => { assert(this.state_ === State.BACKUP); - this.state_ = State.ERROR; + this.state_ = State.BACKUP_ERROR; }), callbackRouter.precheckStatus.addListener((status) => { this.precheckStatus_ = status; @@ -196,11 +197,11 @@ }), callbackRouter.onRestoreFailed.addListener(() => { assert(this.state_ === State.RESTORE); - this.state_ = State.ERROR; + this.state_ = State.RESTORE_ERROR; }), callbackRouter.onCanceled.addListener(() => { if (this.state_ === State.RESTORE) { - this.state_ = State.ERROR; + this.state_ = State.RESTORE_ERROR; return; } this.closePage_(); @@ -278,8 +279,9 @@ this.closePage_(); break; case State.PRECHECKS_FAILED: + case State.BACKUP_ERROR: case State.UPGRADE_ERROR: - case State.ERROR: + case State.RESTORE_ERROR: case State.OFFER_RESTORE: case State.SUCCEEDED: this.closePage_(); @@ -421,6 +423,9 @@ case State.BACKUP: titleId = 'backingUpTitle'; break; + case State.BACKUP_ERROR: + titleId = 'backupErrorTitle'; + break; case State.BACKUP_SUCCEEDED: titleId = 'backupSucceededTitle'; break; @@ -432,12 +437,14 @@ break; case State.OFFER_RESTORE: case State.UPGRADE_ERROR: - case State.ERROR: titleId = 'errorTitle'; break; case State.RESTORE: titleId = 'restoreTitle'; break; + case State.RESTORE_ERROR: + titleId = 'restoreErrorTitle'; + break; case State.RESTORE_SUCCEEDED: titleId = 'restoreSucceededTitle'; break; @@ -464,11 +471,7 @@ return loadTimeData.getString('upgrade'); case State.PRECHECKS_FAILED: return loadTimeData.getString('retry'); - case State.UPGRADE_ERROR: - case State.ERROR: - return loadTimeData.getString('cancel'); case State.SUCCEEDED: - case State.RESTORE_SUCCEEDED: return loadTimeData.getString('done'); case State.OFFER_RESTORE: return loadTimeData.getString('restore'); @@ -483,10 +486,10 @@ */ getCancelButtonLabel_(state) { switch (state) { - case State.SUCCEEDED: case State.RESTORE_SUCCEEDED: + case State.BACKUP_ERROR: case State.UPGRADE_ERROR: - case State.ERROR: + case State.RESTORE_ERROR: return loadTimeData.getString('close'); case State.PROMPT: return loadTimeData.getString('notNow'); @@ -509,6 +512,9 @@ case State.BACKUP: messageId = 'backingUpMessage'; break; + case State.BACKUP_ERROR: + messageId = 'backupErrorMessage'; + break; case State.BACKUP_SUCCEEDED: messageId = 'backupSucceededMessage'; break; @@ -535,6 +541,9 @@ case State.RESTORE: messageId = 'restoreMessage'; break; + case State.RESTORE_ERROR: + messageId = 'restoreErrorMessage'; + break; case State.RESTORE_SUCCEEDED: messageId = 'restoreSucceededMessage'; break; @@ -561,10 +570,11 @@ */ getIllustrationStyle_(state) { switch (state) { + case State.BACKUP_ERROR: case State.BACKUP_SUCCEEDED: + case State.RESTORE_ERROR: case State.RESTORE_SUCCEEDED: case State.PRECHECKS_FAILED: - case State.ERROR: return 'img-square-illustration'; } return 'img-rect-illustration'; @@ -581,7 +591,8 @@ case State.RESTORE_SUCCEEDED: return 'images/success_illustration.svg'; case State.PRECHECKS_FAILED: - case State.ERROR: + case State.BACKUP_ERROR: + case State.RESTORE_ERROR: return 'images/error_illustration.png'; } return 'images/linux_illustration.png';
diff --git a/chrome/browser/resources/extensions/runtime_host_permissions.html b/chrome/browser/resources/extensions/runtime_host_permissions.html index c737501a..dfa7ff5 100644 --- a/chrome/browser/resources/extensions/runtime_host_permissions.html +++ b/chrome/browser/resources/extensions/runtime_host_permissions.html
@@ -217,3 +217,17 @@ on-cancel="onHostDialogCancel_"> </extensions-runtime-hosts-dialog> </template> +<template is="dom-if" if="[[showRemoveSiteDialog_]]" restamp> + <cr-dialog id="removeSitesDialog" on-cancel="onRemoveSitesWarningCancel_" + show-on-attach> + <div slot="title">$i18n{removeSitesDialogTitle}</div> + <div slot="button-container"> + <cr-button class="cancel-button" on-click="onRemoveSitesWarningCancel_"> + $i18n{cancel} + </cr-button> + <cr-button class="action-button" on-click="onRemoveSitesWarningConfirm_"> + $i18n{remove} + </cr-button> + </div> + </cr-dialog> +</template>
diff --git a/chrome/browser/resources/extensions/runtime_host_permissions.ts b/chrome/browser/resources/extensions/runtime_host_permissions.ts index eecbab69..4143965d 100644 --- a/chrome/browser/resources/extensions/runtime_host_permissions.ts +++ b/chrome/browser/resources/extensions/runtime_host_permissions.ts
@@ -3,6 +3,8 @@ // found in the LICENSE file. import 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; +import 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; +import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; import 'chrome://resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; import 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button.m.js'; @@ -18,6 +20,7 @@ import './strings.m.js'; import {CrActionMenuElement} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; +import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js'; import {DomRepeatEvent, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -59,6 +62,15 @@ showHostDialog_: Boolean, /** + * Whether the dialog warning the user that the list of sites added will + * be removed is shown. + */ + showRemoveSiteDialog_: { + type: Boolean, + value: false, + }, + + /** * The current site of the entry that the host dialog is editing, if the * dialog is open for editing. */ @@ -127,6 +139,7 @@ delegate: ItemDelegate; enableEnhancedSiteControls: boolean; private showHostDialog_: boolean; + private showRemoveSiteDialog_: boolean; private hostDialogModel_: string|null; private hostDialogAnchorElement_: HTMLElement|null; private actionMenuModel_: string|null; @@ -140,6 +153,11 @@ return this.shadowRoot!.querySelector<HTMLSelectElement>(selectMenuId)!; } + getRemoveSiteDialog(): CrDialogElement { + return this.shadowRoot!.querySelector<CrDialogElement>( + '#removeSitesDialog')!; + } + private onHostAccessChange_() { const selectMenu = this.getSelectMenu(); const access = selectMenu.value as chrome.developerPrivate.HostAccess; @@ -163,9 +181,10 @@ } } - if (access === chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES && - this.permissions.hostAccess !== - chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES) { + const kOnSpecificSites = + chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES; + if (access === kOnSpecificSites && + this.permissions.hostAccess !== kOnSpecificSites) { // If the user is transitioning to the "on specific sites" option, show // the "add host" dialog. This serves two purposes: // - The user is prompted to add a host immediately, since otherwise @@ -176,6 +195,15 @@ // is properly calculated. this.oldHostAccess_ = this.permissions.hostAccess; this.doShowHostDialog_(selectMenu, null); + } else if ( + this.enableEnhancedSiteControls && access !== kOnSpecificSites && + this.permissions.hostAccess === kOnSpecificSites) { + // If the user is transitioning from the "on specific sites" option to + // another one, show a dialog asking the user to confirm the transition + // because in C++, only the "on specific sites" option will store sites + // the user has added and transitioning away from it will clear these + // sites. + this.showRemoveSiteDialog_ = true; } else { this.delegate.setItemHostAccess(this.itemId, access); } @@ -300,6 +328,25 @@ private getFaviconUrl_(url: string): string { return getFaviconUrl(url); } + + private onRemoveSitesWarningConfirm_() { + this.delegate.setItemHostAccess( + this.itemId, + this.getSelectMenu().value as chrome.developerPrivate.HostAccess); + this.getRemoveSiteDialog().close(); + this.showRemoveSiteDialog_ = false; + } + + private onRemoveSitesWarningCancel_() { + assert( + this.permissions.hostAccess === + chrome.developerPrivate.HostAccess.ON_SPECIFIC_SITES); + this.revertingHostAccess_ = true; + this.getSelectMenu().value = this.permissions.hostAccess; + this.revertingHostAccess_ = false; + this.getRemoveSiteDialog().close(); + this.showRemoveSiteDialog_ = false; + } } declare global {
diff --git a/chrome/browser/resources/feed/BUILD.gn b/chrome/browser/resources/feed/BUILD.gn new file mode 100644 index 0000000..d9eaef8 --- /dev/null +++ b/chrome/browser/resources/feed/BUILD.gn
@@ -0,0 +1,39 @@ +# Copyright 2022 The Chromium 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("//tools/grit/grit_rule.gni") +import("//tools/typescript/ts_library.gni") +import("//ui/webui/resources/tools/generate_grd.gni") + +assert(!is_android) + +grit("resources") { + # This argument is needed since the grd is generated at build time. + enable_input_discovery_for_gn_analyze = false + + source = "$target_gen_dir/resources.grd" + deps = [ ":build_grd" ] + outputs = [ + "grit/feed_resources.h", + "grit/feed_resources_map.cc", + "grit/feed_resources_map.h", + "feed_resources.pak", + ] + output_dir = "$root_gen_dir/chrome" +} + +generate_grd("build_grd") { + grd_prefix = "feed" + out_grd = "$target_gen_dir/resources.grd" + deps = [ ":build_ts" ] + input_files = [ "feed.html" ] + manifest_files = [ "$target_gen_dir/tsconfig.manifest" ] + input_files_base_dir = rebase_path(".", "//") +} + +ts_library("build_ts") { + root_dir = "." + out_dir = "$target_gen_dir/tsc" + in_files = [ "feed.ts" ] +}
diff --git a/chrome/browser/resources/feed/OWNERS b/chrome/browser/resources/feed/OWNERS new file mode 100644 index 0000000..4a7fc50 --- /dev/null +++ b/chrome/browser/resources/feed/OWNERS
@@ -0,0 +1 @@ +file://components/feed/OWNERS
diff --git a/chrome/browser/resources/feed/feed.html b/chrome/browser/resources/feed/feed.html new file mode 100644 index 0000000..26636b6 --- /dev/null +++ b/chrome/browser/resources/feed/feed.html
@@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html lang="$i18n{language}" dir="$i18n{textdirection}"> + <head> + <meta charset="utf-8"> + <title>Feed Untrusted Frame</title> + <meta name="viewport" content="width=device-width"> + </head> + <body> + <h1>Feed Untrusted Frame</h1> + <script type="module" src="$i18n{scriptUrl}"></script> + </body> +</html>
diff --git a/chrome/browser/resources/feed/feed.ts b/chrome/browser/resources/feed/feed.ts new file mode 100644 index 0000000..97422075 --- /dev/null +++ b/chrome/browser/resources/feed/feed.ts
@@ -0,0 +1,5 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +console.log('Success!');
diff --git a/chrome/browser/resources/inline_login/arc_account_picker_app.html b/chrome/browser/resources/inline_login/arc_account_picker_app.html index b4daba5..f14f4eb 100644 --- a/chrome/browser/resources/inline_login/arc_account_picker_app.html +++ b/chrome/browser/resources/inline_login/arc_account_picker_app.html
@@ -110,7 +110,8 @@ <div class="account-item" on-click="makeAvailableInArc_" on-keypress="onAccountKeyPress_" tabindex="0" role="button" - aria-labelledby$="fullName-[[index]] email-[[index]]"> + aria-labelledby$="fullName-[[index]] email-[[index]]" + aria-description="$i18n{accountUseInArcButtonLabel}"> <div class="account-icon" aria-hidden="true" style="background-image: [[getIconImageSet_(item.image)]]"> </div> @@ -125,8 +126,7 @@ <div class="account-item" id="addAccountButton" on-click="addAccount_" on-keypress="onAddAccountKeyPress_" tabindex="0" role="button" - aria-label="$i18n{addAccountLabel}" - aria-description="$i18n{accountUseInArcButtonLabel}"> + aria-label="$i18n{addAccountLabel}"> <div class="account-icon" aria-hidden="true"> <div class="add-icon"></div> </div>
diff --git a/chrome/browser/resources/new_tab_page/app.html b/chrome/browser/resources/new_tab_page/app.html index 0ebe904..1f4517d04 100644 --- a/chrome/browser/resources/new_tab_page/app.html +++ b/chrome/browser/resources/new_tab_page/app.html
@@ -34,7 +34,19 @@ } :host([modules-redesigned-layout-enabled_]) { - --ntp-module-layout-width: 1170px; + --ntp-module-layout-width: 360px; + } + + @media (min-width: 960px) { + :host([modules-redesigned-layout-enabled_]) { + --ntp-module-layout-width: 780px; + } + } + + @media (min-width: 1440px) { + :host([modules-redesigned-layout-enabled_]) { + --ntp-module-layout-width: 1170px; + } } :host([show-background-image_]) {
diff --git a/chrome/browser/resources/new_tab_page/new_tab_page.ts b/chrome/browser/resources/new_tab_page/new_tab_page.ts index b5e20c3..f783e39 100644 --- a/chrome/browser/resources/new_tab_page/new_tab_page.ts +++ b/chrome/browser/resources/new_tab_page/new_tab_page.ts
@@ -37,7 +37,10 @@ export {recipeTasksDescriptor, shoppingTasksDescriptor} from './modules/task_module/module.js'; export {TaskModuleHandlerProxy} from './modules/task_module/task_module_handler_proxy.js'; export {NewTabPageProxy} from './new_tab_page_proxy.js'; +export {RealboxElement} from './realbox/realbox.js'; export {RealboxBrowserProxy} from './realbox/realbox_browser_proxy.js'; +export {RealboxIconElement} from './realbox/realbox_icon.js'; +export {RealboxMatchElement} from './realbox/realbox_match.js'; export {$$, createScrollBorders, decodeString16, mojoString16} from './utils.js'; export {Action as VoiceAction, Error as VoiceError} from './voice_search_overlay.js'; export {WindowProxy} from './window_proxy.js';
diff --git a/chrome/browser/resources/new_tab_page/realbox/realbox.ts b/chrome/browser/resources/new_tab_page/realbox/realbox.ts index b525074..0d086068 100644 --- a/chrome/browser/resources/new_tab_page/realbox/realbox.ts +++ b/chrome/browser/resources/new_tab_page/realbox/realbox.ts
@@ -12,12 +12,12 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {I18nMixin, loadTimeData} from '../i18n_setup.js'; -import {AutocompleteMatch, AutocompleteResult, PageCallbackRouter, PageHandlerRemote, SearchBoxTheme} from '../realbox.mojom-webui.js'; +import {AutocompleteMatch, AutocompleteResult, PageCallbackRouter, PageHandlerInterface, SearchBoxTheme} from '../realbox.mojom-webui.js'; import {decodeString16, mojoString16, mojoTimeDelta} from '../utils.js'; import {RealboxBrowserProxy} from './realbox_browser_proxy.js'; import {RealboxDropdownElement} from './realbox_dropdown.js'; -import {AutocompleteMatchWithImageData} from './realbox_icon.js'; +import {AutocompleteMatchWithImageData, RealboxIconElement} from './realbox_icon.js'; type Input = { text: string, @@ -30,16 +30,18 @@ moveCursorToEnd?: boolean, }; -interface RealboxElement { +export interface RealboxElement { $: { input: HTMLInputElement, inputWrapper: HTMLElement, matches: RealboxDropdownElement, + icon: RealboxIconElement, + voiceSearchButton: HTMLElement, }; } /** A real search box that behaves just like the Omnibox. */ -class RealboxElement extends I18nMixin +export class RealboxElement extends I18nMixin (PolymerElement) { static get is() { return 'ntp-realbox'; @@ -183,7 +185,7 @@ private selectedMatchIndex_: number; private inputAriaLive_: string; - private pageHandler_: PageHandlerRemote; + private pageHandler_: PageHandlerInterface; private callbackRouter_: PageCallbackRouter; private autocompleteResultChangedListenerId_: number|null = null; private autocompleteMatchImageAvailableListenerId_: number|null = null; @@ -723,4 +725,10 @@ } } +declare global { + interface HTMLElementTagNameMap { + 'ntp-realbox': RealboxElement; + } +} + customElements.define(RealboxElement.is, RealboxElement);
diff --git a/chrome/browser/resources/new_tab_page/realbox/realbox_browser_proxy.ts b/chrome/browser/resources/new_tab_page/realbox/realbox_browser_proxy.ts index 99d287a..dc09968 100644 --- a/chrome/browser/resources/new_tab_page/realbox/realbox_browser_proxy.ts +++ b/chrome/browser/resources/new_tab_page/realbox/realbox_browser_proxy.ts
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {PageCallbackRouter, PageHandler, PageHandlerRemote} from '../realbox.mojom-webui.js'; +import {PageCallbackRouter, PageHandler, PageHandlerInterface} from '../realbox.mojom-webui.js'; /** * @fileoverview This file provides a singleton class that exposes the Mojo @@ -21,7 +21,7 @@ instance = newInstance; } - handler: PageHandlerRemote; + handler: PageHandlerInterface; callbackRouter: PageCallbackRouter; constructor() {
diff --git a/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.ts b/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.ts index 5afa587..aa6324c2 100644 --- a/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.ts +++ b/chrome/browser/resources/new_tab_page/realbox/realbox_dropdown.ts
@@ -11,16 +11,17 @@ import {skColorToRgba} from 'chrome://resources/js/color_utils.js'; import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js'; import {IronSelectorElement} from 'chrome://resources/polymer/v3_0/iron-selector/iron-selector.js'; -import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {DomRepeat, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {loadTimeData} from '../i18n_setup.js'; -import {AutocompleteMatch, AutocompleteResult, PageCallbackRouter, PageHandlerRemote, SearchBoxTheme} from '../realbox.mojom-webui.js'; +import {AutocompleteMatch, AutocompleteResult, PageCallbackRouter, PageHandlerInterface, SearchBoxTheme} from '../realbox.mojom-webui.js'; import {decodeString16} from '../utils.js'; import {RealboxBrowserProxy} from './realbox_browser_proxy.js'; export interface RealboxDropdownElement { $: { + groups: DomRepeat, selector: IronSelectorElement, }; } @@ -94,7 +95,7 @@ private selectableMatchElements_: Element[]; private callbackRouter_: PageCallbackRouter; - private pageHandler_: PageHandlerRemote; + private pageHandler_: PageHandlerInterface; private autocompleteMatchImageAvailableListenerId_: number|null = null; constructor() {
diff --git a/chrome/browser/resources/new_tab_page/realbox/realbox_icon.ts b/chrome/browser/resources/new_tab_page/realbox/realbox_icon.ts index 240dc2e..da834cf 100644 --- a/chrome/browser/resources/new_tab_page/realbox/realbox_icon.ts +++ b/chrome/browser/resources/new_tab_page/realbox/realbox_icon.ts
@@ -11,9 +11,17 @@ export type AutocompleteMatchWithImageData = AutocompleteMatch&{faviconDataUrl?: string, imageDataUrl?: string}; +export interface RealboxIconElement { + $: { + container: HTMLElement, + icon: HTMLElement, + image: HTMLImageElement, + }; +} + // The LHS icon. Used on autocomplete matches as well as the realbox input to // render icons, favicons, and entity images. -class RealboxIconElement extends PolymerElement { +export class RealboxIconElement extends PolymerElement { static get is() { return 'ntp-realbox-icon'; }
diff --git a/chrome/browser/resources/new_tab_page/realbox/realbox_match.ts b/chrome/browser/resources/new_tab_page/realbox/realbox_match.ts index 193def0..c79db28 100644 --- a/chrome/browser/resources/new_tab_page/realbox/realbox_match.ts +++ b/chrome/browser/resources/new_tab_page/realbox/realbox_match.ts
@@ -11,12 +11,13 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {loadTimeData} from '../i18n_setup.js'; -import {ACMatchClassification, AutocompleteMatch, PageHandlerRemote} from '../realbox.mojom-webui.js'; +import {ACMatchClassification, AutocompleteMatch, PageHandlerInterface} from '../realbox.mojom-webui.js'; import {decodeString16, mojoTimeTicks} from '../utils.js'; import {RealboxBrowserProxy} from './realbox_browser_proxy.js'; - +import {RealboxIconElement} from './realbox_icon.js'; // clang-format off + /** * Bitmap used to decode the value of ACMatchClassification style * field. @@ -30,8 +31,19 @@ } // clang-format on +export interface RealboxMatchElement { + $: { + icon: RealboxIconElement, + contents: HTMLElement, + description: HTMLElement, + remove: HTMLElement, + separator: HTMLElement, + 'focus-indicator': HTMLElement, + }; +} + // Displays an autocomplete match similar to those in the Omnibox. -class RealboxMatchElement extends PolymerElement { +export class RealboxMatchElement extends PolymerElement { static get is() { return 'ntp-realbox-match'; } @@ -129,7 +141,7 @@ private separatorText_: string; private tailSuggestPrefix_: string; - private pageHandler_: PageHandlerRemote; + private pageHandler_: PageHandlerInterface; constructor() { super(); @@ -353,4 +365,10 @@ } } +declare global { + interface HTMLElementTagNameMap { + 'ntp-realbox-match': RealboxMatchElement; + } +} + customElements.define(RealboxMatchElement.is, RealboxMatchElement);
diff --git a/chrome/browser/resources/pdf/BUILD.gn b/chrome/browser/resources/pdf/BUILD.gn index e1d3f49..22840d7 100644 --- a/chrome/browser/resources/pdf/BUILD.gn +++ b/chrome/browser/resources/pdf/BUILD.gn
@@ -191,7 +191,10 @@ manifest_excludes = [ "pdf_internal_plugin_wrapper.js" ] + print_preview_non_webcomponents_files + print_preview_webcomponents_files - definitions = [ "//tools/typescript/definitions/metrics_private.d.ts" ] + definitions = [ + "//tools/typescript/definitions/metrics_private.d.ts", + "source_capabilities.d.ts", + ] deps = [ "//third_party/polymer/v3_0:library", "//ui/webui/resources:library",
diff --git a/chrome/browser/resources/pdf/elements/viewer-page-indicator.js b/chrome/browser/resources/pdf/elements/viewer-page-indicator.ts similarity index 81% rename from chrome/browser/resources/pdf/elements/viewer-page-indicator.js rename to chrome/browser/resources/pdf/elements/viewer-page-indicator.ts index 95ae8aa..01c78054f 100644 --- a/chrome/browser/resources/pdf/elements/viewer-page-indicator.js +++ b/chrome/browser/resources/pdf/elements/viewer-page-indicator.ts
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -import {assert} from 'chrome://resources/js/assert.m.js'; +import {assert} from 'chrome://resources/js/assert_ts.js'; import {isRTL} from 'chrome://resources/js/util.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -27,17 +27,12 @@ }; } - constructor() { - super(); + label: string; + index: number; + pageLabels: number[]|null; + timerId?: number; + private viewport_: Viewport|null = null; - /** @type {number|undefined} */ - this.timerId = undefined; - - /** @private @type {?Viewport} */ - this.viewport_ = null; - } - - /** @override */ ready() { super.ready(); const callback = this.fadeIn_.bind(this); @@ -46,13 +41,11 @@ }); } - /** @param {!Viewport} viewport */ - setViewport(viewport) { + setViewport(viewport: Viewport) { this.viewport_ = viewport; } - /** @private */ - fadeIn_() { + private fadeIn_() { // Vertically position relative to scroll position. let percent = 0; if (this.viewport_) { @@ -72,11 +65,11 @@ this.style[isRTL() ? 'left' : 'right'] = `${overlayScrollbarWidth}px`; // Animate opacity. - this.style.opacity = 1; + this.style.opacity = '1'; clearTimeout(this.timerId); this.timerId = setTimeout(() => { - this.style.opacity = 0; + this.style.opacity = '0'; this.timerId = undefined; }, 2000); } @@ -87,12 +80,18 @@ indexChanged() { if (this.pageLabels) { - this.label = this.pageLabels[this.index]; + this.label = String(this.pageLabels[this.index]); } else { this.label = String(this.index + 1); } } } +declare global { + interface HTMLElementTagNameMap { + 'viewer-page-indicator': ViewerPageIndicatorElement; + } +} + customElements.define( ViewerPageIndicatorElement.is, ViewerPageIndicatorElement);
diff --git a/chrome/browser/resources/pdf/pdf.gni b/chrome/browser/resources/pdf/pdf.gni index 46e54de..b91f274c 100644 --- a/chrome/browser/resources/pdf/pdf.gni +++ b/chrome/browser/resources/pdf/pdf.gni
@@ -51,15 +51,15 @@ # Files to pass directly to preprocess_if_expr() that are used only in Print # Preview. -print_preview_non_webcomponents_files = [ "toolbar_manager.js" ] +print_preview_non_webcomponents_files = [ "toolbar_manager.ts" ] # Files that need to be passed to html_to_js() that are used only in Print # Preview. print_preview_webcomponents_files = [ - "elements/viewer-page-indicator.js", + "elements/viewer-page-indicator.ts", "elements/viewer-zoom-button.ts", "elements/viewer-zoom-toolbar.ts", - "pdf_viewer_pp.js", + "pdf_viewer_pp.ts", ] # Files to pass directly to preprocess_if_expr() that are shared by PDF Viewer
diff --git a/chrome/browser/resources/pdf/pdf_viewer_base.js b/chrome/browser/resources/pdf/pdf_viewer_base.js index 3a0749bb..3db00d0 100644 --- a/chrome/browser/resources/pdf/pdf_viewer_base.js +++ b/chrome/browser/resources/pdf/pdf_viewer_base.js
@@ -38,10 +38,6 @@ return 'pdf-viewer-base'; } - static get template() { - return null; - } - static get properties() { return { /** @protected */
diff --git a/chrome/browser/resources/pdf/pdf_viewer_pp.html b/chrome/browser/resources/pdf/pdf_viewer_pp.html index b376d90..5f1bcca 100644 --- a/chrome/browser/resources/pdf/pdf_viewer_pp.html +++ b/chrome/browser/resources/pdf/pdf_viewer_pp.html
@@ -20,12 +20,12 @@ <div id="sizer"></div> -<viewer-zoom-toolbar id="zoom-toolbar" +<viewer-zoom-toolbar id="zoomToolbar" on-fit-to-changed="onFitToChanged" on-zoom-in="onZoomIn" on-zoom-out="onZoomOut"> </viewer-zoom-toolbar> -<viewer-page-indicator id="page-indicator"></viewer-page-indicator> +<viewer-page-indicator id="pageIndicator"></viewer-page-indicator> <div id="content"></div>
diff --git a/chrome/browser/resources/pdf/pdf_viewer_pp.js b/chrome/browser/resources/pdf/pdf_viewer_pp.ts similarity index 65% rename from chrome/browser/resources/pdf/pdf_viewer_pp.js rename to chrome/browser/resources/pdf/pdf_viewer_pp.ts index 405b411..d106a46 100644 --- a/chrome/browser/resources/pdf/pdf_viewer_pp.js +++ b/chrome/browser/resources/pdf/pdf_viewer_pp.ts
@@ -8,7 +8,7 @@ import './elements/viewer-zoom-toolbar.js'; import './pdf_viewer_shared_style.js'; -import {assertNotReached} from 'chrome://resources/js/assert.m.js'; +import {assertNotReached} from 'chrome://resources/js/assert_ts.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {isRTL} from 'chrome://resources/js/util.m.js'; import {html} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; @@ -23,7 +23,24 @@ import {DestinationMessageData, DocumentDimensionsMessageData, hasCtrlModifier, MessageObject, shouldIgnoreKeyEvents} from './pdf_viewer_utils.js'; import {ToolbarManager} from './toolbar_manager.js'; -class PDFViewerPPElement extends PDFViewerBaseElement { + +type KeyEventData = MessageData&{keyEvent: Object}; + +type ExtendedKeyEvent = KeyboardEvent&{ + fromScriptingAPI?: boolean, + fromPlugin?: boolean, +}; + +export interface PDFViewerPPElement { + $: { + content: HTMLDivElement, + pageIndicator: ViewerPageIndicatorElement, + sizer: HTMLDivElement, + zoomToolbar: ViewerZoomToolbarElement, + }; +} + +export class PDFViewerPPElement extends PDFViewerBaseElement { static get is() { return 'pdf-viewer-pp'; } @@ -32,78 +49,43 @@ return html`{__html_template__}`; } - constructor() { - super(); + private isPrintPreviewLoadingFinished_: boolean = false; + private inPrintPreviewMode_: boolean = false; + private dark_: boolean = false; + private pluginController_: PluginController|undefined = undefined; + private toolbarManager_: ToolbarManager|null = null; - /** @private {boolean} */ - this.isPrintPreviewLoadingFinished_ = false; - - /** @private {boolean} */ - this.inPrintPreviewMode_ = false; - - /** @private {boolean} */ - this.dark_ = false; - - /** @private {?ToolbarManager} */ - this.toolbarManager_ = null; - } - - /** @override */ ready() { super.ready(); window.addEventListener('scroll', () => { - this.pluginController_.updateScroll(window.scrollX, window.scrollY); + this.pluginController_!.updateScroll(window.scrollX, window.scrollY); }); } - /** @override */ isNewUiEnabled() { return false; } - /** @override */ getBackgroundColor() { return PRINT_PREVIEW_BACKGROUND_COLOR; } - /** - * @return {!ViewerPageIndicatorElement} - * @private - */ - getPageIndicator_() { - return /** @type {!ViewerPageIndicatorElement} */ ( - this.$$('#page-indicator')); - } - - /** - * @return {!ViewerZoomToolbarElement} - * @private - */ - getZoomToolbar_() { - return /** @type {!ViewerZoomToolbarElement} */ (this.$$('#zoom-toolbar')); - } - - /** @param {!BrowserApi} browserApi */ - init(browserApi) { + init(browserApi: BrowserApi) { super.init( - browserApi, document.documentElement, - /** @type {!HTMLDivElement} */ (this.$$('#sizer')), - /** @type {!HTMLDivElement} */ (this.$$('#content'))); + browserApi, document.documentElement, this.$.sizer, this.$.content); - /** @private {?PluginController} */ this.pluginController_ = PluginController.getInstance(); - this.getPageIndicator_().setViewport(this.viewport); - this.toolbarManager_ = new ToolbarManager(window, this.getZoomToolbar_()); + this.$.pageIndicator.setViewport(this.viewport); + this.toolbarManager_ = new ToolbarManager(window, this.$.zoomToolbar); } - /** @override */ - handleKeyEvent(e) { + handleKeyEvent(e: ExtendedKeyEvent) { if (shouldIgnoreKeyEvents() || e.defaultPrevented) { return; } - this.toolbarManager_.hideToolbarAfterTimeout(); + this.toolbarManager_!.hideToolbarAfterTimeout(); // Let the viewport handle directional key events. if (this.viewport.handleDirectionalKeyEvent(e, false)) { return; @@ -111,20 +93,20 @@ switch (e.key) { case 'Tab': - this.toolbarManager_.showToolbarForKeyboardNavigation(); + this.toolbarManager_!.showToolbarForKeyboardNavigation(); return; case 'Escape': break; // Ensure escape falls through to the print-preview handler. case 'a': if (hasCtrlModifier(e)) { - this.pluginController_.selectAll(); + this.pluginController_!.selectAll(); // Since we do selection ourselves. e.preventDefault(); } return; case '\\': if (e.ctrlKey) { - this.getZoomToolbar_().fitToggleFromHotKey(); + this.$.zoomToolbar.fitToggleFromHotKey(); } return; } @@ -136,19 +118,17 @@ } else { // Show toolbar as a fallback. if (!(e.shiftKey || e.ctrlKey || e.altKey)) { - this.getZoomToolbar_().show(); + this.$.zoomToolbar.show(); } } } - /** @private */ - setBackgroundColorForPrintPreview_() { - this.pluginController_.setBackgroundColor( + private setBackgroundColorForPrintPreview_() { + this.pluginController_!.setBackgroundColor( this.dark_ ? PRINT_PREVIEW_DARK_BACKGROUND_COLOR : PRINT_PREVIEW_BACKGROUND_COLOR); } - /** @override */ updateUIForViewportChange() { // Offset the toolbar position so that it doesn't move if scrollbars appear. const hasScrollbars = this.viewport.documentHasScrollbars(); @@ -164,7 +144,7 @@ // than the spec. In LTR layout, the zoom toolbar is on the left // left side, but the scrollbar is still on the right, so this is not // necessary. - const zoomToolbar = this.getZoomToolbar_(); + const zoomToolbar = this.$.zoomToolbar; if (isRTL()) { zoomToolbar.style.right = -verticalScrollbarWidth + (scrollbarWidth / 2) + 'px'; @@ -177,21 +157,20 @@ // Update the page indicator. const visiblePage = this.viewport.getMostVisiblePage(); - const pageIndicator = this.getPageIndicator_(); + const pageIndicator = this.$.pageIndicator; const lastIndex = pageIndicator.index; pageIndicator.index = visiblePage; - if (this.documentDimensions.pageDimensions.length > 1 && + if (this.documentDimensions!.pageDimensions.length > 1 && hasScrollbars.vertical && lastIndex !== undefined) { pageIndicator.style.visibility = 'visible'; } else { pageIndicator.style.visibility = 'hidden'; } - this.pluginController_.viewportChanged(); + this.pluginController_!.viewportChanged(); } - /** @override */ - handleScriptingMessage(message) { + handleScriptingMessage(message: MessageObject) { if (super.handleScriptingMessage(message)) { return true; } @@ -206,11 +185,11 @@ switch (message.data.type.toString()) { case 'getSelectedText': - this.pluginController_.getSelectedText().then( + this.pluginController_!.getSelectedText().then( this.sendScriptingMessage.bind(this)); break; case 'selectAll': - this.pluginController_.selectAll(); + this.pluginController_!.selectAll(); break; default: return false; @@ -220,21 +199,20 @@ /** * Handle scripting messages specific to print preview. - * @param {!MessageObject} message the message to handle. - * @return {boolean} true if the message was handled, false otherwise. - * @private + * @param message the message to handle. + * @return true if the message was handled, false otherwise. */ - handlePrintPreviewScriptingMessage_(message) { - let messageData = message.data; + private handlePrintPreviewScriptingMessage_(message: MessageObject): boolean { + const messageData = message.data; switch (messageData.type.toString()) { case 'loadPreviewPage': - messageData = - /** @type {{ url: string, index: number }} */ (messageData); - this.pluginController_.loadPreviewPage( - messageData.url, messageData.index); + const loadData = + messageData as MessageData & {url: string, index: number}; + this.pluginController_!.loadPreviewPage(loadData.url, loadData.index); return true; case 'resetPrintPreviewMode': - messageData = /** @type {!PrintPreviewParams} */ (messageData); + const printPreviewData = + messageData as (MessageData & PrintPreviewParams); this.setLoadState(LoadState.LOADING); if (!this.inPrintPreviewMode_) { this.inPrintPreviewMode_ = true; @@ -247,28 +225,31 @@ // Stash the scroll location so that it can be restored when the new // document is loaded. this.lastViewportPosition = this.viewport.position; - this.getPageIndicator_().pageLabels = messageData.pageNumbers; + this.$.pageIndicator.pageLabels = printPreviewData.pageNumbers; - this.pluginController_.resetPrintPreviewMode(messageData); + this.pluginController_!.resetPrintPreviewMode(printPreviewData); return true; case 'sendKeyEvent': - const keyEvent = DeserializeKeyEvent( - /** @type {{ keyEvent: Object }} */ (message.data).keyEvent); - keyEvent.fromScriptingAPI = true; - this.handleKeyEvent(keyEvent); + const keyEvent = + DeserializeKeyEvent((message.data as KeyEventData).keyEvent); + const extendedKeyEvent = keyEvent as ExtendedKeyEvent; + extendedKeyEvent.fromScriptingAPI = true; + this.handleKeyEvent(extendedKeyEvent); return true; case 'hideToolbar': - this.toolbarManager_.resetKeyboardNavigationAndHideToolbar(); + this.toolbarManager_!.resetKeyboardNavigationAndHideToolbar(); return true; case 'darkModeChanged': - this.dark_ = /** @type {{darkMode: boolean}} */ (message.data).darkMode; + this.dark_ = + (message.data as (MessageData & {darkMode: boolean})).darkMode; this.setBackgroundColorForPrintPreview_(); return true; case 'scrollPosition': const position = this.viewport.position; - messageData = /** @type {{ x: number, y: number }} */ (message.data); - position.y += messageData.y; - position.x += messageData.x; + const positionData = + message.data as (MessageData & {x: number, y: number}); + position.y += positionData.y; + position.x += positionData.x; this.viewport.setPosition(position); return true; } @@ -276,28 +257,24 @@ return false; } - /** @override */ - setLoadState(loadState) { + setLoadState(loadState: LoadState) { super.setLoadState(loadState); if (loadState === LoadState.FAILED) { this.isPrintPreviewLoadingFinished_ = true; } } - /** @override */ - handlePluginMessage(e) { + handlePluginMessage(e: CustomEvent) { const data = e.detail; switch (data.type.toString()) { case 'documentDimensions': - this.setDocumentDimensions( - /** @type {!DocumentDimensionsMessageData} */ (data)); + this.setDocumentDimensions(data as DocumentDimensionsMessageData); return; case 'loadProgress': - this.updateProgress( - /** @type {{ progress: number }} */ (data).progress); + this.updateProgress((data as {progress: number}).progress); return; case 'navigateToDestination': - const destinationData = /** @type {!DestinationMessageData} */ (data); + const destinationData = data as DestinationMessageData; this.viewport.handleNavigateToDestination( destinationData.page, destinationData.x, destinationData.y, destinationData.zoom); @@ -306,8 +283,8 @@ this.handlePrintPreviewLoaded_(); return; case 'setIsSelecting': - this.viewportScroller.setEnableScrolling( - /** @type {{ isSelecting: boolean }} */ (data).isSelecting); + this.viewportScroller!.setEnableScrolling( + (data as (MessageData & {isSelecting: boolean})).isSelecting); return; case 'touchSelectionOccurred': this.sendScriptingMessage({ @@ -318,8 +295,8 @@ // TODO(crbug.com/1069370): Draw a focus rect around plugin. return; case 'sendKeyEvent': - const keyEvent = DeserializeKeyEvent( - /** @type {{ keyEvent: Object }} */ (data).keyEvent); + const keyEvent = DeserializeKeyEvent((data as KeyEventData).keyEvent) as + ExtendedKeyEvent; keyEvent.fromPlugin = true; this.handleKeyEvent(keyEvent); return; @@ -338,25 +315,21 @@ /** * Handles a notification that print preview has loaded from the * current controller. - * @private */ - handlePrintPreviewLoaded_() { + private handlePrintPreviewLoaded_() { this.isPrintPreviewLoadingFinished_ = true; this.sendDocumentLoadedMessage(); } - /** @override */ readyToSendLoadMessage() { return this.isPrintPreviewLoadingFinished_; } - /** @override */ - forceFit(view) { - this.getZoomToolbar_().forceFit(view); + forceFit(view: FittingType) { + this.$.zoomToolbar.forceFit(view); } - /** @override */ - handleStrings(strings) { + handleStrings(strings: {[key: string]: string}) { super.handleStrings(strings); if (!strings) { return; @@ -364,11 +337,10 @@ this.setBackgroundColorForPrintPreview_(); } - /** @override */ - updateProgress(progress) { + updateProgress(progress: number) { super.updateProgress(progress); if (progress === 100) { - this.toolbarManager_.hideToolbarAfterTimeout(); + this.toolbarManager_!.hideToolbarAfterTimeout(); } } } @@ -376,15 +348,19 @@ /** * The background color used for print preview (--google-grey-300). Keep * in sync with `ChromePdfStreamDelegate::MapToOriginalUrl()`. - * @type {number} */ -const PRINT_PREVIEW_BACKGROUND_COLOR = 0xffdadce0; +const PRINT_PREVIEW_BACKGROUND_COLOR: number = 0xffdadce0; /** * The background color used for print preview when dark mode is enabled * (--google-grey-700). - * @type {number} */ -const PRINT_PREVIEW_DARK_BACKGROUND_COLOR = 0xff5f6368; +const PRINT_PREVIEW_DARK_BACKGROUND_COLOR: number = 0xff5f6368; + +declare global { + interface HTMLElementTagNameMap { + 'pdf-viewer-pp': PDFViewerPPElement; + } +} customElements.define(PDFViewerPPElement.is, PDFViewerPPElement);
diff --git a/chrome/browser/resources/pdf/source_capabilities.d.ts b/chrome/browser/resources/pdf/source_capabilities.d.ts new file mode 100644 index 0000000..fd3c8ab4 --- /dev/null +++ b/chrome/browser/resources/pdf/source_capabilities.d.ts
@@ -0,0 +1,16 @@ +// Copyright 2022 The Chromium 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 currently a Chrome only API, and the spec is still in working draft +// stage. +// https://developer.mozilla.org/en-US/docs/Web/API/UIEvent/sourceCapabilities + +interface UIEvent extends Event { + readonly sourceCapabilities: InputDeviceCapabilities|null; +} + +declare class InputDeviceCapabilities { + constructor(param: {firesTouchEvents: boolean}); + readonly firesTouchEvents: boolean; +}
diff --git a/chrome/browser/resources/pdf/toolbar_manager.js b/chrome/browser/resources/pdf/toolbar_manager.ts similarity index 65% rename from chrome/browser/resources/pdf/toolbar_manager.js rename to chrome/browser/resources/pdf/toolbar_manager.ts index db38cef..d2f5404 100644 --- a/chrome/browser/resources/pdf/toolbar_manager.js +++ b/chrome/browser/resources/pdf/toolbar_manager.ts
@@ -7,37 +7,32 @@ /** * Idle time in ms before the UI is hidden. - * @type {number} */ -const HIDE_TIMEOUT = 2000; +const HIDE_TIMEOUT: number = 2000; /** * Velocity required in a mousemove to reveal the UI (pixels/ms). This is * intended to be high enough that a fast flick of the mouse is required to * reach it. - * @type {number} */ -const SHOW_VELOCITY = 10; +const SHOW_VELOCITY: number = 10; /** * Distance from right of the screen required to reveal toolbars. - * @type {number} */ -const TOOLBAR_REVEAL_DISTANCE_RIGHT = 150; +const TOOLBAR_REVEAL_DISTANCE_RIGHT: number = 150; /** * Distance from bottom of the screen required to reveal toolbars. - * @type {number} */ -const TOOLBAR_REVEAL_DISTANCE_BOTTOM = 250; +const TOOLBAR_REVEAL_DISTANCE_BOTTOM: number = 250; /** - * @param {!MouseEvent} e Event to test. - * @param {Window} window Window to test against. - * @return {boolean} True if the mouse is close to the bottom-right of the - * screen. + * @param e Event to test. + * @param window Window to test against. + * @return True if the mouse is close to the bottom-right of the screen. */ -function isMouseNearToolbar(e, window) { +function isMouseNearToolbar(e: MouseEvent, window: Window): boolean { const atSide = isRTL() ? e.x > window.innerWidth - TOOLBAR_REVEAL_DISTANCE_RIGHT : e.x < TOOLBAR_REVEAL_DISTANCE_RIGHT; @@ -47,49 +42,35 @@ // Responsible for showing and hiding the zoom toolbar. export class ToolbarManager { - /** - * @param {!Window} window The window containing the UI. - * @param {!ViewerZoomToolbarElement} zoomToolbar - */ - constructor(window, zoomToolbar) { - /** @private {!Window} */ - this.window_ = window; + private window_: Window; + private zoomToolbar_: ViewerZoomToolbarElement; + private toolbarTimeout_: number|null = null; + private isMouseNearToolbar_: boolean = false; + private keyboardNavigationActive_: boolean = false; + private lastMovementTimestamp_: number|null = null; - /** @private {!ViewerZoomToolbarElement} */ + /** + * @param window The window containing the UI. + */ + constructor(window: Window, zoomToolbar: ViewerZoomToolbarElement) { + this.window_ = window; this.zoomToolbar_ = zoomToolbar; - /** @private {?number} */ - this.toolbarTimeout_ = null; - - /** @private {boolean} */ - this.isMouseNearToolbar_ = false; - - /** @private {boolean} */ - this.keyboardNavigationActive = false; - - /** @private {?number} */ - this.lastMovementTimestamp = null; - - document.addEventListener( - 'mousemove', - e => this.handleMouseMove_(/** @type {!MouseEvent} */ (e))); + document.addEventListener('mousemove', e => this.handleMouseMove_(e)); document.addEventListener('mouseout', () => this.hideToolbarForMouseOut_()); this.zoomToolbar_.addEventListener('keyboard-navigation-active', e => { - this.keyboardNavigationActive = e.detail; + this.keyboardNavigationActive_ = (e as CustomEvent).detail; }); } - /** - * @param {!MouseEvent} e - * @private - */ - handleMouseMove_(e) { + private handleMouseMove_(e: MouseEvent) { this.isMouseNearToolbar_ = isMouseNearToolbar(e, this.window_); - this.keyboardNavigationActive = false; + this.keyboardNavigationActive_ = false; + const touchInteractionActive = - (e.sourceCapabilities && e.sourceCapabilities.firesTouchEvents); + e.sourceCapabilities && e.sourceCapabilities.firesTouchEvents; // Tapping the screen with toolbars open tries to close them. if (touchInteractionActive && this.zoomToolbar_.isVisible()) { @@ -108,21 +89,17 @@ /** * Whether a mousemove event is high enough velocity to reveal the toolbars. - * @param {!MouseEvent} e Event to test. - * @return {boolean} true if the event is a high velocity mousemove, false - * otherwise. - * @private */ - isHighVelocityMouseMove_(e) { + private isHighVelocityMouseMove_(e: MouseEvent): boolean { if (e.type === 'mousemove') { - if (this.lastMovementTimestamp == null) { - this.lastMovementTimestamp = this.getCurrentTimestamp_(); + if (this.lastMovementTimestamp_ == null) { + this.lastMovementTimestamp_ = this.getCurrentTimestamp(); } else { const movement = Math.sqrt(e.movementX * e.movementX + e.movementY * e.movementY); - const newTime = this.getCurrentTimestamp_(); - const interval = newTime - this.lastMovementTimestamp; - this.lastMovementTimestamp = newTime; + const newTime = this.getCurrentTimestamp(); + const interval = newTime - this.lastMovementTimestamp_; + this.lastMovementTimestamp_ = newTime; if (interval !== 0) { return movement / interval > SHOW_VELOCITY; @@ -134,10 +111,8 @@ /** * Wrapper around Date.now() to make it easily replaceable for testing. - * @return {number} - * @private */ - getCurrentTimestamp_() { + getCurrentTimestamp(): number { return Date.now(); } @@ -147,16 +122,15 @@ * escape is pressed. */ showToolbarForKeyboardNavigation() { - this.keyboardNavigationActive = true; + this.keyboardNavigationActive_ = true; this.zoomToolbar_.show(); } /** * Hide toolbars after a delay, regardless of the position of the mouse. * Intended to be called when the mouse has moved out of the parent window. - * @private */ - hideToolbarForMouseOut_() { + private hideToolbarForMouseOut_() { this.isMouseNearToolbar_ = false; this.hideToolbarAfterTimeout(); } @@ -165,17 +139,16 @@ * Check if the toolbar is able to be closed, and close it if it is. * Toolbar may be kept open based on mouse/keyboard activity and active * elements. - * @private */ - hideToolbarIfAllowed_() { - if (this.isMouseNearToolbar_ || this.keyboardNavigationActive) { + private hideToolbarIfAllowed_() { + if (this.isMouseNearToolbar_ || this.keyboardNavigationActive_) { return; } // Remove focus to make any visible tooltips disappear -- otherwise they'll // still be visible on screen when the toolbar is off screen. if (document.activeElement === this.zoomToolbar_) { - document.activeElement.blur(); + this.zoomToolbar_.blur(); } this.zoomToolbar_.hide(); @@ -194,7 +167,7 @@ * Clears the keyboard navigation state and hides the toolbars after a delay. */ resetKeyboardNavigationAndHideToolbar() { - this.keyboardNavigationActive = false; + this.keyboardNavigationActive_ = false; this.hideToolbarAfterTimeout(); } }
diff --git a/chrome/browser/resources/settings/BUILD.gn b/chrome/browser/resources/settings/BUILD.gn index f3b6a5e..14cc095 100644 --- a/chrome/browser/resources/settings/BUILD.gn +++ b/chrome/browser/resources/settings/BUILD.gn
@@ -9,6 +9,7 @@ import("//tools/grit/grit_rule.gni") import("//tools/grit/preprocess_if_expr.gni") import("//tools/polymer/html_to_js.gni") +import("//tools/polymer/html_to_wrapper.gni") import("//tools/typescript/ts_library.gni") import("//ui/webui/resources/tools/generate_grd.gni") import("//ui/webui/webui_features.gni") @@ -121,17 +122,20 @@ preprocess_if_expr("preprocess") { defines = chrome_grit_defines - in_folder = "./" + in_folder = "." out_folder = "$target_gen_dir/$preprocess_folder" - in_files = non_webcomponent_files + in_files = ts_files } preprocess_if_expr("preprocess_generated") { defines = chrome_grit_defines - deps = [ ":web_components" ] + deps = [ + ":css_wrapper_files", + ":html_wrapper_files", + ] in_folder = target_gen_dir out_folder = "$target_gen_dir/$preprocess_folder" - in_files = web_component_files + in_files = html_wrapper_files + css_wrapper_files } grit("resources") { @@ -226,8 +230,12 @@ extra_deps = [ ":build_ts" ] } -html_to_js("web_components") { - js_files = web_component_files +html_to_js("css_wrapper_files") { + js_files = css_wrapper_files +} + +html_to_wrapper("html_wrapper_files") { + in_files = html_files } ts_library("build_ts") { @@ -235,7 +243,7 @@ out_dir = "$target_gen_dir/tsc" composite = true tsconfig_base = "tsconfig_base.json" - in_files = web_component_files + non_webcomponent_files + in_files = ts_files + css_wrapper_files + html_wrapper_files deps = [ "//third_party/polymer/v3_0:library",
diff --git a/chrome/browser/resources/settings/a11y_page/a11y_page.ts b/chrome/browser/resources/settings/a11y_page/a11y_page.ts index 2109b4ac..22ac6c01 100644 --- a/chrome/browser/resources/settings/a11y_page/a11y_page.ts +++ b/chrome/browser/resources/settings/a11y_page/a11y_page.ts
@@ -12,7 +12,6 @@ import '../controls/settings_toggle_button.js'; import '../settings_page/settings_animated_pages.js'; import '../settings_shared_css.js'; - // <if expr="not is_macosx and not chromeos"> import './captions_subpage.js'; import '../settings_page/settings_subpage.js'; @@ -20,6 +19,7 @@ // <if expr="is_win or is_macosx"> import './live_caption_section.js'; + // </if> import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; @@ -31,8 +31,10 @@ import {routes} from '../route.js'; import {Router} from '../router.js'; +import {getTemplate} from './a11y_page.html.js'; // <if expr="is_win or is_macosx"> import {CaptionsBrowserProxyImpl} from './captions_browser_proxy.js'; + // </if> const SettingsA11YPageElementBase = @@ -44,7 +46,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/a11y_page/captions_subpage.ts b/chrome/browser/resources/settings/a11y_page/captions_subpage.ts index 2a9a8a8..af4f2aaa 100644 --- a/chrome/browser/resources/settings/a11y_page/captions_subpage.ts +++ b/chrome/browser/resources/settings/a11y_page/captions_subpage.ts
@@ -21,6 +21,8 @@ import {loadTimeData} from '../i18n_setup.js'; import {PrefsMixin} from '../prefs/prefs_mixin.js'; +import {getTemplate} from './captions_subpage.html.js'; + const SettingsCaptionsElementBase = PrefsMixin(PolymerElement); class SettingsCaptionsElement extends SettingsCaptionsElementBase { @@ -29,7 +31,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/a11y_page/live_caption_section.ts b/chrome/browser/resources/settings/a11y_page/live_caption_section.ts index 610d2c8..fbea9b7 100644 --- a/chrome/browser/resources/settings/a11y_page/live_caption_section.ts +++ b/chrome/browser/resources/settings/a11y_page/live_caption_section.ts
@@ -21,6 +21,8 @@ import {loadTimeData} from '../i18n_setup.js'; import {PrefsMixin} from '../prefs/prefs_mixin.js'; +import {getTemplate} from './live_caption_section.html.js'; + /** * |name| is the display name of a language, ex. German. @@ -45,7 +47,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/about_page/about_page.ts b/chrome/browser/resources/settings/about_page/about_page.ts index 73237d5b..7f54794 100644 --- a/chrome/browser/resources/settings/about_page/about_page.ts +++ b/chrome/browser/resources/settings/about_page/about_page.ts
@@ -32,6 +32,7 @@ import {loadTimeData} from '../i18n_setup.js'; import {RelaunchMixin, RestartType} from '../relaunch_mixin.js'; +import {getTemplate} from './about_page.html.js'; import {AboutPageBrowserProxy, AboutPageBrowserProxyImpl, UpdateStatus, UpdateStatusChangedEvent} from './about_page_browser_proxy.js'; // <if expr="_google_chrome and is_macosx"> import {PromoteUpdaterStatus} from './about_page_browser_proxy.js'; @@ -47,7 +48,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts index 293ad42..4b5825e8 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts +++ b/chrome/browser/resources/settings/appearance_page/appearance_fonts_page.ts
@@ -13,6 +13,7 @@ import {DropdownMenuOptionList} from '../controls/settings_dropdown_menu.js'; +import {getTemplate} from './appearance_fonts_page.html.js'; import {FontsBrowserProxy, FontsBrowserProxyImpl, FontsData} from './fonts_browser_proxy.js'; @@ -49,7 +50,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/appearance_page/appearance_page.ts b/chrome/browser/resources/settings/appearance_page/appearance_page.ts index 95b8cd7..ce62c27e 100644 --- a/chrome/browser/resources/settings/appearance_page/appearance_page.ts +++ b/chrome/browser/resources/settings/appearance_page/appearance_page.ts
@@ -32,6 +32,7 @@ import {Router} from '../router.js'; import {AppearanceBrowserProxy, AppearanceBrowserProxyImpl} from './appearance_browser_proxy.js'; +import {getTemplate} from './appearance_page.html.js'; /** @@ -68,7 +69,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/appearance_page/home_url_input.ts b/chrome/browser/resources/settings/appearance_page/home_url_input.ts index bb7b27d..f5b372c 100644 --- a/chrome/browser/resources/settings/appearance_page/home_url_input.ts +++ b/chrome/browser/resources/settings/appearance_page/home_url_input.ts
@@ -18,6 +18,7 @@ import {PrefControlMixin} from '../controls/pref_control_mixin.js'; import {AppearanceBrowserProxy, AppearanceBrowserProxyImpl} from './appearance_browser_proxy.js'; +import {getTemplate} from './home_url_input.html.js'; export interface HomeUrlInputElement { $: { @@ -35,7 +36,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/address_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/address_edit_dialog.ts index 9456c30..28d5adbf 100644 --- a/chrome/browser/resources/settings/autofill_page/address_edit_dialog.ts +++ b/chrome/browser/resources/settings/autofill_page/address_edit_dialog.ts
@@ -25,6 +25,8 @@ import {loadTimeData} from '../i18n_setup.js'; +import {getTemplate} from './address_edit_dialog.html.js'; + export interface SettingsAddressEditDialogElement { $: { dialog: CrDialogElement, @@ -44,7 +46,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/address_remove_confirmation_dialog.ts b/chrome/browser/resources/settings/autofill_page/address_remove_confirmation_dialog.ts index 57643f052..f9ef96a 100644 --- a/chrome/browser/resources/settings/autofill_page/address_remove_confirmation_dialog.ts +++ b/chrome/browser/resources/settings/autofill_page/address_remove_confirmation_dialog.ts
@@ -11,6 +11,7 @@ import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './address_remove_confirmation_dialog.html.js'; export interface SettingsAddressRemoveConfirmationDialogElement { @@ -28,7 +29,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } wasConfirmed(): boolean {
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_page.ts b/chrome/browser/resources/settings/autofill_page/autofill_page.ts index 960fc27..a05a129 100644 --- a/chrome/browser/resources/settings/autofill_page/autofill_page.ts +++ b/chrome/browser/resources/settings/autofill_page/autofill_page.ts
@@ -21,6 +21,7 @@ import {routes} from '../route.js'; import {Router} from '../router.js'; +import {getTemplate} from './autofill_page.html.js'; import {PasswordCheckMixin} from './password_check_mixin.js'; import {PasswordManagerImpl} from './password_manager_proxy.js'; @@ -34,7 +35,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/autofill_section.ts b/chrome/browser/resources/settings/autofill_page/autofill_section.ts index 770046b..e412f8520 100644 --- a/chrome/browser/resources/settings/autofill_page/autofill_section.ts +++ b/chrome/browser/resources/settings/autofill_page/autofill_section.ts
@@ -31,6 +31,7 @@ import {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js'; import {AutofillManagerImpl, AutofillManagerProxy, PersonalDataChangedListener} from './autofill_manager_proxy.js'; +import {getTemplate} from './autofill_section.html.js'; declare global { interface HTMLElementEventMap { @@ -58,7 +59,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/avatar_icon.ts b/chrome/browser/resources/settings/autofill_page/avatar_icon.ts index b3f1f66..9100e03 100644 --- a/chrome/browser/resources/settings/autofill_page/avatar_icon.ts +++ b/chrome/browser/resources/settings/autofill_page/avatar_icon.ts
@@ -12,6 +12,8 @@ import {StoredAccount, SyncBrowserProxyImpl} from '../people_page/sync_browser_proxy.js'; +import {getTemplate} from './avatar_icon.html.js'; + const SettingsAvatarIconElementBase = WebUIListenerMixin(PolymerElement); class SettingsAvatarIconElement extends SettingsAvatarIconElementBase { @@ -20,7 +22,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.ts index 227d40b2..26ea096 100644 --- a/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.ts +++ b/chrome/browser/resources/settings/autofill_page/credit_card_edit_dialog.ts
@@ -22,6 +22,7 @@ import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {html, microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './credit_card_edit_dialog.html.js'; /** * Regular expression for invalid nickname. Nickname containing any digits will @@ -58,7 +59,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts index 22947f3..ab80c1e1 100644 --- a/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts +++ b/chrome/browser/resources/settings/autofill_page/credit_card_list_entry.ts
@@ -15,8 +15,11 @@ import {I18nMixin} from '//resources/js/i18n_mixin.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + import {loadTimeData} from '../i18n_setup.js'; +import {getTemplate} from './credit_card_list_entry.html.js'; + const SettingsCreditCardListEntryElementBase = I18nMixin(PolymerElement); class SettingsCreditCardListEntryElement extends @@ -26,7 +29,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/password_check.ts b/chrome/browser/resources/settings/autofill_page/password_check.ts index a844507..bfacab3f0 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check.ts +++ b/chrome/browser/resources/settings/autofill_page/password_check.ts
@@ -46,6 +46,7 @@ import {BlockingRequestManager} from './blocking_request_manager.js'; // </if> +import {getTemplate} from './password_check.html.js'; import {PasswordCheckListItemElement} from './password_check_list_item.js'; import {PasswordCheckMixin, PasswordCheckMixinInterface} from './password_check_mixin.js'; import {PasswordCheckInteraction, SavedPasswordListChangedListener} from './password_manager_proxy.js'; @@ -73,7 +74,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts index ad5cec0c..02f654b9 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts +++ b/chrome/browser/resources/settings/autofill_page/password_check_edit_dialog.ts
@@ -24,6 +24,7 @@ import {focusWithoutInk} from 'chrome://resources/js/cr/ui/focus_without_ink.m.js'; import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './password_check_edit_dialog.html.js'; import {PasswordCheckInteraction, PasswordManagerImpl, PasswordManagerProxy} from './password_manager_proxy.js'; @@ -44,7 +45,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_edit_disclaimer_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_check_edit_disclaimer_dialog.ts index 9a3eda10..731bf66d 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check_edit_disclaimer_dialog.ts +++ b/chrome/browser/resources/settings/autofill_page/password_check_edit_disclaimer_dialog.ts
@@ -8,6 +8,7 @@ import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './password_check_edit_disclaimer_dialog.html.js'; interface SettingsPasswordEditDisclaimerDialogElement { $: { @@ -25,7 +26,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts b/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts index 30439b0..794dc3f 100644 --- a/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts +++ b/chrome/browser/resources/settings/autofill_page/password_check_list_item.ts
@@ -23,6 +23,8 @@ // <if expr="chromeos_ash or chromeos_lacros"> import {BlockingRequestManager} from './blocking_request_manager.js'; // </if> + +import {getTemplate} from './password_check_list_item.html.js'; import {PasswordCheckInteraction, PasswordManagerImpl, PasswordManagerProxy} from './password_manager_proxy.js'; @@ -32,7 +34,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts index 55c746a..2a4c7a5 100644 --- a/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts +++ b/chrome/browser/resources/settings/autofill_page/password_edit_dialog.ts
@@ -29,6 +29,7 @@ import {BlockingRequestManager} from './blocking_request_manager.js'; // </if> import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js'; +import {getTemplate} from './password_edit_dialog.html.js'; import {PasswordManagerImpl} from './password_manager_proxy.js'; export interface PasswordEditDialogElement { @@ -93,7 +94,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/password_list_item.ts b/chrome/browser/resources/settings/autofill_page/password_list_item.ts index bc4f8f55..067c27d6 100644 --- a/chrome/browser/resources/settings/autofill_page/password_list_item.ts +++ b/chrome/browser/resources/settings/autofill_page/password_list_item.ts
@@ -19,6 +19,7 @@ import {loadTimeData} from '../i18n_setup.js'; +import {getTemplate} from './password_list_item.html.js'; import {ShowPasswordMixin, ShowPasswordMixinInterface} from './show_password_mixin.js'; export type PasswordMoreActionsClickedEvent = CustomEvent<{ @@ -43,7 +44,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.ts index f460ac30..63796ed 100644 --- a/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.ts +++ b/chrome/browser/resources/settings/autofill_page/password_move_multiple_passwords_to_account_dialog.ts
@@ -19,6 +19,7 @@ import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js'; import {PasswordManagerImpl} from './password_manager_proxy.js'; +import {getTemplate} from './password_move_multiple_passwords_to_account_dialog.html.js'; import {MoveToAccountStoreTrigger} from './password_move_to_account_dialog.js'; export interface PasswordMoveMultiplePasswordsToAccountDialogElement { @@ -36,7 +37,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.ts index e948890..e9ba84b6 100644 --- a/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.ts +++ b/chrome/browser/resources/settings/autofill_page/password_move_to_account_dialog.ts
@@ -20,6 +20,7 @@ import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js'; import {PasswordManagerImpl} from './password_manager_proxy.js'; +import {getTemplate} from './password_move_to_account_dialog.html.js'; /** * This should be kept in sync with the enum in @@ -48,7 +49,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/password_remove_confirmation_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_remove_confirmation_dialog.ts index 12f35cd..9fec5ad4 100644 --- a/chrome/browser/resources/settings/autofill_page/password_remove_confirmation_dialog.ts +++ b/chrome/browser/resources/settings/autofill_page/password_remove_confirmation_dialog.ts
@@ -12,6 +12,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {PasswordCheckInteraction, PasswordManagerImpl, PasswordManagerProxy} from './password_manager_proxy.js'; +import {getTemplate} from './password_remove_confirmation_dialog.html.js'; interface SettingsPasswordRemoveConfirmationDialogElement { $: { @@ -29,7 +30,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/password_remove_dialog.ts b/chrome/browser/resources/settings/autofill_page/password_remove_dialog.ts index 4cc5d9d9..1b82b77 100644 --- a/chrome/browser/resources/settings/autofill_page/password_remove_dialog.ts +++ b/chrome/browser/resources/settings/autofill_page/password_remove_dialog.ts
@@ -25,6 +25,7 @@ import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js'; import {PasswordManagerImpl} from './password_manager_proxy.js'; +import {getTemplate} from './password_remove_dialog.html.js'; export type PasswordRemoveDialogPasswordsRemovedEvent = CustomEvent<{removedFromAccount: boolean, removedFromDevice: boolean}>; @@ -43,7 +44,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_device_section.ts b/chrome/browser/resources/settings/autofill_page/passwords_device_section.ts index 9cb7186..78e9ac8 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_device_section.ts +++ b/chrome/browser/resources/settings/autofill_page/passwords_device_section.ts
@@ -39,6 +39,7 @@ import {MergePasswordsStoreCopiesMixin, MergePasswordsStoreCopiesMixinInterface} from './merge_passwords_store_copies_mixin.js'; import {MultiStorePasswordUiEntry} from './multi_store_password_ui_entry.js'; import {AccountStorageOptInStateChangedListener, PasswordManagerImpl} from './password_manager_proxy.js'; +import {getTemplate} from './passwords_device_section.html.js'; import {PasswordsListHandlerElement} from './passwords_list_handler.js'; /** @@ -83,7 +84,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.ts b/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.ts index 1060889..8520570f 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.ts +++ b/chrome/browser/resources/settings/autofill_page/passwords_export_dialog.ts
@@ -21,6 +21,7 @@ import {BlockingRequestManager} from './blocking_request_manager.js'; // </if> import {PasswordManagerImpl, PasswordManagerProxy, PasswordsFileExportProgressListener} from './password_manager_proxy.js'; +import {getTemplate} from './passwords_export_dialog.html.js'; /** @@ -55,7 +56,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.ts b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.ts index e87e74e..6b5d1a4 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_list_handler.ts +++ b/chrome/browser/resources/settings/autofill_page/passwords_list_handler.ts
@@ -36,6 +36,7 @@ import {PasswordListItemElement, PasswordMoreActionsClickedEvent} from './password_list_item.js'; import {PasswordManagerImpl, PasswordManagerProxy} from './password_manager_proxy.js'; import {PasswordRemoveDialogPasswordsRemovedEvent} from './password_remove_dialog.js'; +import {getTemplate} from './passwords_list_handler.html.js'; declare global { interface HTMLElementEventMap { @@ -64,7 +65,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.html b/chrome/browser/resources/settings/autofill_page/passwords_section.html index 2d1cd6d..44dfa61 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_section.html +++ b/chrome/browser/resources/settings/autofill_page/passwords_section.html
@@ -102,12 +102,6 @@ label="$i18n{passwordsAutosigninLabel}" sub-label="$i18n{passwordsAutosigninDescription}"> </settings-toggle-button> - <cr-link-row id="trustedVaultBanner" label="$i18n{trustedVaultBannerLabel}" - sub-label="[[ - getTrustedVaultBannerSubLabel_(trustedVaultBannerState_)]]" - hidden$="[[shouldHideTrustedVaultBanner_(trustedVaultBannerState_)]]" - on-click="onTrustedVaultBannerClick_" external> - </cr-link-row> <div id="checkPasswordsBannerContainer" class="cr-row" hidden$="[[!shouldShowBanner_]]"> <picture> @@ -151,6 +145,12 @@ aria-label="$i18n{checkPasswords}"> </cr-icon-button> </div> + <cr-link-row id="trustedVaultBanner" class="cr-row" + label="$i18n{trustedVaultBannerLabel}" sub-label="[[ + getTrustedVaultBannerSubLabel_(trustedVaultBannerState_)]]" + hidden$="[[shouldHideTrustedVaultBanner_(trustedVaultBannerState_)]]" + on-click="onTrustedVaultBannerClick_" external> + </cr-link-row> <div id="manageLink" class="cr-row two-line" hidden$="[[hidePasswordsLink_]]"> <!-- This div lays out the link correctly, relative to the text. -->
diff --git a/chrome/browser/resources/settings/autofill_page/passwords_section.ts b/chrome/browser/resources/settings/autofill_page/passwords_section.ts index af63392..ccc6199e 100644 --- a/chrome/browser/resources/settings/autofill_page/passwords_section.ts +++ b/chrome/browser/resources/settings/autofill_page/passwords_section.ts
@@ -59,6 +59,7 @@ import {AddCredentialFromSettingsUserInteractions} from './password_edit_dialog.js'; import {PasswordCheckReferrer, PasswordExceptionListChangedListener, PasswordManagerImpl, PasswordManagerProxy} from './password_manager_proxy.js'; import {PasswordsListHandlerElement} from './passwords_list_handler.js'; +import {getTemplate} from './passwords_section.html.js'; /** * Checks if an HTML element is an editable. An editable is either a text @@ -92,7 +93,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/payments_list.ts b/chrome/browser/resources/settings/autofill_page/payments_list.ts index df0fe303..85acd00 100644 --- a/chrome/browser/resources/settings/autofill_page/payments_list.ts +++ b/chrome/browser/resources/settings/autofill_page/payments_list.ts
@@ -17,13 +17,15 @@ import {loadTimeData} from '../i18n_setup.js'; +import {getTemplate} from './payments_list.html.js'; + class SettingsPaymentsListElement extends PolymerElement { static get is() { return 'settings-payments-list'; } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/payments_section.ts b/chrome/browser/resources/settings/autofill_page/payments_section.ts index c26e7d38..9753959 100644 --- a/chrome/browser/resources/settings/autofill_page/payments_section.ts +++ b/chrome/browser/resources/settings/autofill_page/payments_section.ts
@@ -33,6 +33,7 @@ import {PersonalDataChangedListener} from './autofill_manager_proxy.js'; import {PaymentsManagerImpl, PaymentsManagerProxy} from './payments_manager_proxy.js'; +import {getTemplate} from './payments_section.html.js'; type DotsCardMenuiClickEvent = CustomEvent<{ @@ -71,7 +72,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/autofill_page/upi_id_list_entry.ts b/chrome/browser/resources/settings/autofill_page/upi_id_list_entry.ts index 41f53ac..d7352827 100644 --- a/chrome/browser/resources/settings/autofill_page/upi_id_list_entry.ts +++ b/chrome/browser/resources/settings/autofill_page/upi_id_list_entry.ts
@@ -13,6 +13,7 @@ import '../settings_shared_css.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './upi_id_list_entry.html.js'; class SettingsUpiIdListEntryElement extends PolymerElement { static get is() { @@ -20,7 +21,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/basic_page/basic_page.ts b/chrome/browser/resources/settings/basic_page/basic_page.ts index 352d18910..f4209a2 100644 --- a/chrome/browser/resources/settings/basic_page/basic_page.ts +++ b/chrome/browser/resources/settings/basic_page/basic_page.ts
@@ -46,6 +46,8 @@ import {getSearchManager, SearchResult} from '../search_settings.js'; import {MainPageMixin, MainPageMixinInterface} from '../settings_page/main_page_mixin.js'; +import {getTemplate} from './basic_page.html.js'; + // <if expr="chromeos_ash or chromeos_lacros"> const OS_BANNER_INTERACTION_METRIC_NAME = 'ChromeOS.Settings.OsBannerInteraction'; @@ -81,7 +83,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.ts b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.ts index 112cb49..0c11bc04 100644 --- a/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.ts +++ b/chrome/browser/resources/settings/chrome_cleanup_page/chrome_cleanup_page.ts
@@ -22,6 +22,8 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SettingsCheckboxElement} from '../controls/settings_checkbox.js'; + +import {getTemplate} from './chrome_cleanup_page.html.js'; import {ChromeCleanupProxy, ChromeCleanupProxyImpl} from './chrome_cleanup_proxy.js'; import {ChromeCleanupRemovalListItem} from './items_to_remove_list.js'; @@ -133,7 +135,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.ts b/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.ts index 2e22a90..849f327 100644 --- a/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.ts +++ b/chrome/browser/resources/settings/chrome_cleanup_page/items_to_remove_list.ts
@@ -9,6 +9,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {ChromeCleanupProxyImpl} from './chrome_cleanup_proxy.js'; +import {getTemplate} from './items_to_remove_list.html.js'; /** * For each line in the item list, the text field will be shown in normal @@ -51,7 +52,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/chromeos/BUILD.gn b/chrome/browser/resources/settings/chromeos/BUILD.gn index 8e8ddfd..dcf7b46 100644 --- a/chrome/browser/resources/settings/chromeos/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/BUILD.gn
@@ -280,6 +280,7 @@ "chromeos/os_apps_page/app_management_page/util.js", "chromeos/os_apps_page/app_management_page/types.js", "chromeos/os_apps_page/app_notifications_page/mojo_interface_provider.js", + "chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_browser_proxy.js", "chromeos/os_languages_page/input_method_settings.js", "chromeos/os_languages_page/languages_browser_proxy.js", "chromeos/os_languages_page/languages.js", @@ -324,51 +325,64 @@ in_folder = "$root_gen_dir/chrome/browser/resources/settings/tsc" out_folder = "$target_gen_dir/$preprocess_folder_v3" out_manifest = "$target_gen_dir/$browser_settings_tsc_manifest" - in_files = [ + + # Files that have a corresponding HTML wrapper file. + settings_web_component_files = [ "a11y_page/captions_subpage.js", "a11y_page/live_caption_section.js", - "appearance_page/fonts_browser_proxy.js", "controls/controlled_button.js", "controls/controlled_radio_button.js", - "controls/cr_policy_pref_mixin.js", "controls/extension_controlled_indicator.js", "controls/password_prompt_dialog.js", - "controls/pref_control_mixin.js", - "controls/settings_boolean_control_mixin.js", "controls/settings_dropdown_menu.js", "controls/settings_radio_group.js", "controls/settings_slider.js", "controls/settings_textarea.js", "controls/settings_toggle_button.js", + "people_page/signout_dialog.js", + "people_page/sync_account_control.js", + "people_page/sync_controls.js", + "people_page/sync_encryption_options.js", + "people_page/sync_page.js", + "privacy_page/personalization_options.js", + "privacy_page/secure_dns_input.js", + "privacy_page/secure_dns.js", + "settings_page/settings_animated_pages.js", + "settings_page/settings_section.js", + "settings_page/settings_subpage.js", + ] + + in_files = [ + # Files that don't have a corresponding HTML file. + "appearance_page/fonts_browser_proxy.js", + "controls/cr_policy_pref_mixin.js", + "controls/pref_control_mixin.js", + "controls/settings_boolean_control_mixin.js", "extension_control_browser_proxy.js", "i18n_setup.js", "icons.js", "lifetime_browser_proxy.js", "open_window_proxy.js", "people_page/profile_info_browser_proxy.js", - "people_page/signout_dialog.js", - "people_page/sync_account_control.js", "people_page/sync_browser_proxy.js", - "people_page/sync_controls.js", - "people_page/sync_encryption_options.js", - "people_page/sync_page.js", "prefs/prefs.js", "prefs/prefs_mixin.js", "prefs/prefs_types.js", "prefs/pref_util.js", - "privacy_page/personalization_options.js", "privacy_page/privacy_page_browser_proxy.js", - "privacy_page/secure_dns_input.js", - "privacy_page/secure_dns.js", "relaunch_mixin.js", "setting_id_param_util.js", "settings_page_css.js", - "settings_page/settings_animated_pages.js", - "settings_page/settings_section.js", - "settings_page/settings_subpage.js", "settings_shared_css.js", "settings_vars_css.js", ] + + foreach(f, settings_web_component_files) { + in_files += [ + f, + string_replace(f, ".js", ".html.js"), + ] + } } preprocess_if_expr("preprocess_gen_v3") { @@ -475,6 +489,7 @@ "chromeos/os_bluetooth_page/os_bluetooth_page.js", "chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js", "chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js", + "chromeos/os_bluetooth_page/os_bluetooth_true_wireless_images.js", "chromeos/os_bluetooth_page/os_bluetooth_change_device_name_dialog.js", "chromeos/os_bluetooth_page/os_bluetooth_pairing_dialog.js", "chromeos/os_bluetooth_page/os_bluetooth_summary.js", @@ -817,7 +832,8 @@ ":os_settings_icons_css_module", # Shared with browser settings - "..:web_components", + "..:css_wrapper_files", + "..:html_wrapper_files", ] }
diff --git a/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn index 8835abb..dda896ab 100644 --- a/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/nearby_share_page/BUILD.gn
@@ -176,7 +176,8 @@ ":nearby_share_high_visibility_page_module", ":nearby_share_receive_dialog_module", ":nearby_share_subpage_module", - "../..:web_components", + "../..:css_wrapper_files", + "../..:html_wrapper_files", "//chrome/browser/ui/webui/nearby_share:mojom_js", ] }
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js index afb9b2e..c754fae 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/supported_links_item.js
@@ -120,9 +120,6 @@ * @private */ isHidden_(app) { - if (!loadTimeData.getBoolean('appManagementIntentSettingsEnabled')) { - return true; - } return !app.supportedLinks.length; },
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn index d57b011d..b76098f 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/BUILD.gn
@@ -13,9 +13,11 @@ ":os_bluetooth_change_device_name_dialog", ":os_bluetooth_device_detail_subpage", ":os_bluetooth_devices_subpage", + ":os_bluetooth_devices_subpage_browser_proxy", ":os_bluetooth_page", ":os_bluetooth_pairing_dialog", ":os_bluetooth_summary", + ":os_bluetooth_true_wireless_images", ":os_paired_bluetooth_list", ":os_paired_bluetooth_list_item", ":settings_fast_pair_toggle", @@ -35,6 +37,7 @@ js_library("os_bluetooth_devices_subpage") { deps = [ + ":os_bluetooth_devices_subpage_browser_proxy", ":os_paired_bluetooth_list", ":settings_fast_pair_toggle", "..:deep_linking_behavior.m", @@ -45,9 +48,15 @@ "//ui/webui/resources/cr_components/chromeos/bluetooth:bluetooth_metrics_utils", "//ui/webui/resources/cr_components/chromeos/bluetooth:cros_bluetooth_config", "//ui/webui/resources/js:i18n_behavior.m", + "//ui/webui/resources/js:web_ui_listener_behavior.m", ] } +js_library("os_bluetooth_devices_subpage_browser_proxy") { + deps = [ "//ui/webui/resources/js:cr.m" ] + externs_list = [ "$externs_path/chrome_send.js" ] +} + js_library("os_bluetooth_summary") { deps = [ "..:os_route.m", @@ -82,9 +91,18 @@ ] } +js_library("os_bluetooth_true_wireless_images") { + deps = [ + "//third_party/polymer/v3_0/components-chromium/polymer:polymer_bundled", + "//ui/webui/resources/cr_components/chromeos/bluetooth:bluetooth_utils", + "//ui/webui/resources/js:i18n_behavior.m", + ] +} + js_library("os_bluetooth_device_detail_subpage") { deps = [ ":os_bluetooth_change_device_name_dialog", + ":os_bluetooth_true_wireless_images", "..:os_route.m", "..:route_observer_behavior", "..:route_origin_behavior.m", @@ -129,6 +147,7 @@ "os_bluetooth_page.js", "os_bluetooth_summary.js", "os_bluetooth_device_detail_subpage.js", + "os_bluetooth_true_wireless_images.js", "os_bluetooth_change_device_name_dialog.js", "os_bluetooth_pairing_dialog.js", "settings_fast_pair_toggle.js",
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.html b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.html index 510082d..2adc668 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.html +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.html
@@ -86,6 +86,13 @@ </div> </div> <template is="dom-if" + if="[[shouldShowTrueWirelessImages_(device_.*)]]" restamp> + <os-settings-bluetooth-true-wireless-images + id="trueWirelessImages" + device="[[device_.deviceProperties]]"> + </os-settings-bluetooth-true-wireless-images> + </template> + <template is="dom-if" if="[[shouldShowNonAudioOutputDeviceMessage_(device_.*)]]" restamp> <div id="nonAudioOutputDeviceMessage" class="settings-box settings-box-text continuation"
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js index 7822b7a..630fb88 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_device_detail_subpage.js
@@ -12,6 +12,7 @@ import '//resources/cr_elements/cr_icon_button/cr_icon_button.m.js'; import '//resources/cr_elements/policy/cr_tooltip_icon.m.js'; import './os_bluetooth_change_device_name_dialog.js'; +import './os_bluetooth_true_wireless_images.js'; import 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_device_battery_info.js'; import {BluetoothUiSurface, recordBluetoothUiSurfaceMetrics} from '//resources/cr_components/chromeos/bluetooth/bluetooth_metrics_utils.js'; @@ -19,7 +20,7 @@ import {I18nBehavior, I18nBehaviorInterface} from '//resources/js/i18n_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {BatteryType} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_types.js'; -import {getBatteryPercentage, getDeviceName, hasAnyDetailedBatteryInfo} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_utils.js'; +import {getBatteryPercentage, getDeviceName, hasAnyDetailedBatteryInfo, hasTrueWirelessImages} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_utils.js'; import {getBluetoothConfig} from 'chrome://resources/cr_components/chromeos/bluetooth/cros_bluetooth_config.js'; import {loadTimeData} from '../../i18n_setup.js'; @@ -471,16 +472,41 @@ return false; } + // Don't show the inline Battery Info if we are showing the True + // Wireless Images component. + if (this.shouldShowTrueWirelessImages_()) { + return false; + } + if (getBatteryPercentage( this.device_.deviceProperties, BatteryType.DEFAULT) !== undefined) { return true; } - return hasAnyDetailedBatteryInfo(this.device_.deviceProperties); } /** + * @return {boolean} + * @private + */ + shouldShowTrueWirelessImages_() { + if (!this.device_) { + return false; + } + + // Don't show True Wireless Images component if the device has no + // detailed battery info to display. This doesn't matter if the device + // is not connected. + if (!hasAnyDetailedBatteryInfo(this.device_.deviceProperties) && + this.isDeviceConnected_) { + return false; + } + + return hasTrueWirelessImages(this.device_.deviceProperties); + } + + /** * @param {!Event} event * @private */
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.html b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.html index d37411e7..95affc3 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.html +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.html
@@ -71,6 +71,7 @@ </div> </template> </div> -<template is="dom-if" if="[[isFastPairAllowed_]]"> +<template is="dom-if" + if="[[isFastPairToggleVisible_(isFastPairSupportedByDevice_)]]"> <settings-fast-pair-toggle prefs="{{prefs}}"></settings-fast-pair-toggle> </template> \ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js index ef99840d0..b6bc2c0 100644 --- a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage.js
@@ -13,6 +13,7 @@ import {BluetoothUiSurface, recordBluetoothUiSurfaceMetrics} from '//resources/cr_components/chromeos/bluetooth/bluetooth_metrics_utils.js'; import {I18nBehavior, I18nBehaviorInterface} from '//resources/js/i18n_behavior.m.js'; +import {WebUIListenerBehavior, WebUIListenerBehaviorInterface} from '//resources/js/web_ui_listener_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {getBluetoothConfig} from 'chrome://resources/cr_components/chromeos/bluetooth/cros_bluetooth_config.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; @@ -22,6 +23,7 @@ import {DeepLinkingBehavior, DeepLinkingBehaviorInterface} from '../deep_linking_behavior.m.js'; import {routes} from '../os_route.m.js'; import {RouteObserverBehavior, RouteObserverBehaviorInterface} from '../route_observer_behavior.js'; +import {OsBluetoothDevicesSubpageBrowserProxy, OsBluetoothDevicesSubpageBrowserProxyImpl} from './os_bluetooth_devices_subpage_browser_proxy.js'; const mojom = chromeos.bluetoothConfig.mojom; @@ -31,9 +33,14 @@ * @implements {I18nBehaviorInterface} * @implements {RouteObserverBehaviorInterface} * @implements {DeepLinkingBehaviorInterface} + * @implements {WebUIListenerBehaviorInterface} */ const SettingsBluetoothDevicesSubpageElementBase = mixinBehaviors( - [I18nBehavior, RouteObserverBehavior, DeepLinkingBehavior], PolymerElement); + [ + I18nBehavior, RouteObserverBehavior, DeepLinkingBehavior, + WebUIListenerBehavior + ], + PolymerElement); /** @polymer */ class SettingsBluetoothDevicesSubpageElement extends @@ -83,15 +90,12 @@ }, /** - * Whether or not the fast pair feature flag is enabled which controls if - * the fast pair toggle shows up. + * Whether or not this device has the requirements to support fast pair. * @private {boolean} */ - isFastPairAllowed_: { + isFastPairSupportedByDevice_: { type: Boolean, - value: function() { - return loadTimeData.getBoolean('enableFastPairFlag'); - } + value: true, }, /** @@ -120,12 +124,23 @@ * @private {?string} */ this.lastSelectedDeviceId_ = null; + + /** @private {?OsBluetoothDevicesSubpageBrowserProxy} */ + this.browserProxy_ = + OsBluetoothDevicesSubpageBrowserProxyImpl.getInstance(); } /** @override */ ready() { super.ready(); IronA11yAnnouncer.requestAvailability(); + if (loadTimeData.getBoolean('enableFastPairFlag')) { + this.addWebUIListener( + 'fast-pair-device-supported-status', (isSupported) => { + this.isFastPairSupportedByDevice_ = isSupported; + }); + this.browserProxy_.requestFastPairDeviceSupport(); + } } /** @@ -280,6 +295,15 @@ } })); } + + /** + * @return {boolean} + * @private + */ + isFastPairToggleVisible_() { + return this.isFastPairSupportedByDevice_ && + loadTimeData.getBoolean('enableFastPairFlag'); + } } customElements.define(
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_browser_proxy.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_browser_proxy.js new file mode 100644 index 0000000..6ecf32c --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_browser_proxy.js
@@ -0,0 +1,30 @@ +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// clang-format off +import {addSingletonGetter} from 'chrome://resources/js/cr.m.js'; +// clang-format on + +/** @interface */ +export class OsBluetoothDevicesSubpageBrowserProxy { + /** + * Requests whether the Fast Pair feature is supported by the device. + * Returned by the 'fast-pair-device-supported' WebUI listener event. + */ + requestFastPairDeviceSupport() {} +} + +/** + * @implements {OsBluetoothDevicesSubpageBrowserProxy} + */ +export class OsBluetoothDevicesSubpageBrowserProxyImpl { + /** @override */ + requestFastPairDeviceSupport() { + chrome.send('requestFastPairDeviceSupportStatus'); + } +} + +// The singleton instance_ is replaced with a test version of this wrapper +// during testing. +addSingletonGetter(OsBluetoothDevicesSubpageBrowserProxyImpl); \ No newline at end of file
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_true_wireless_images.html b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_true_wireless_images.html new file mode 100644 index 0000000..41df625 --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_true_wireless_images.html
@@ -0,0 +1,93 @@ +<style include="settings-shared"> + #container { + align-items: center; + display: flex; + flex-direction: row; + justify-content: space-around; + margin: 7% 10%; + } + + .image-wrapper { + padding-bottom: 16px; + } + + .image-wrapper img { + border: 1px solid lightgrey; + border-radius: 50%; + height: 70px; + width: 70px; + } + + .battery-container { + align-items: center; + display: flex; + flex-direction: column; + justify-content: center; + } + + #notConnectedLabel { + color: gray; + } +</style> +<div id="container"> + <template is="dom-if" restamp + if="[[shouldShowBatteryTypeInfo_(device, BatteryType.LEFT_BUD)]]"> + <div id="leftBudContainer" class="battery-container"> + <div class="image-wrapper"> + <img src="[[getImageSrc_(device, BatteryType.LEFT_BUD)]]" + alt="Left bud device image"> + </div> + <span id="leftBudLabel"> + [[getBatteryTypeString_(device, BatteryType.LEFT_BUD)]] + </span> + <bluetooth-battery-icon-percentage + device="[[device]]" + battery-type="[[BatteryType.LEFT_BUD]]"> + </bluetooth-battery-icon-percentage> + </div> + </template> + <template is="dom-if" restamp + if="[[shouldShowBatteryTypeInfo_(device, BatteryType.CASE)]]"> + <div id="caseContainer" class="battery-container"> + <div class="image-wrapper"> + <img src="[[getImageSrc_(device, BatteryType.CASE)]]" + alt="Case device image"> + </div> + <span id="caseLabel"> + [[getBatteryTypeString_(device, BatteryType.CASE)]] + </span> + <bluetooth-battery-icon-percentage + device="[[device]]" + battery-type="[[BatteryType.CASE]]"> + </bluetooth-battery-icon-percentage> + </div> + </template> + <template is="dom-if" restamp + if="[[shouldShowBatteryTypeInfo_(device, BatteryType.RIGHT_BUD)]]"> + <div id="rightBudContainer" class="battery-container"> + <div class="image-wrapper"> + <img src="[[getImageSrc_(device, BatteryType.RIGHT_BUD)]]" + alt="Right bud device image"> + </div> + <span id="rightBudLabel"> + [[getBatteryTypeString_(device, BatteryType.RIGHT_BUD)]] + </span> + <bluetooth-battery-icon-percentage + device="[[device]]" + battery-type="[[BatteryType.RIGHT_BUD]]"> + </bluetooth-battery-icon-percentage> + </div> + </template> + <template is="dom-if" restamp + if="[[shouldShowNotConnectedInfo_(device)]]"> + <div id="notConnectedContainer" class="battery-container"> + <div class="image-wrapper"> + <img src="[[getImageSrc_(device, BatteryType.CASE)]]" + alt="Case device image"> + </div> + <span id="notConnectedLabel"> + $i18n{bluetoothDeviceDetailDisconnected} + </span> + </div> + </template> +</div>
diff --git a/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_true_wireless_images.js b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_true_wireless_images.js new file mode 100644 index 0000000..64fa96a --- /dev/null +++ b/chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_true_wireless_images.js
@@ -0,0 +1,142 @@ +// Copyright 2022 The Chromium 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 + * View displaying Bluetooth device True Wireless Images and battery + * information. + */ + +import '../../settings_shared_css.js'; +import 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_battery_icon_percentage.js'; + +import {assertNotReached} from '//resources/js/assert.m.js'; +import {I18nBehavior, I18nBehaviorInterface} from '//resources/js/i18n_behavior.m.js'; +import {html, mixinBehaviors, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {BatteryType} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_types.js'; +import {getBatteryPercentage, hasTrueWirelessImages} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_utils.js'; + +/** + * @constructor + * @extends {PolymerElement} + * @implements {I18nBehaviorInterface} + */ +const SettingsBluetoothTrueWirelessImagesElementBase = + mixinBehaviors([I18nBehavior], PolymerElement); + +/** @polymer */ +export class SettingsBluetoothTrueWirelessImagesElement extends + SettingsBluetoothTrueWirelessImagesElementBase { + static get is() { + return 'os-settings-bluetooth-true-wireless-images'; + } + + static get template() { + return html`{__html_template__}`; + } + + static get properties() { + return { + /** + * @type {!chromeos.bluetoothConfig.mojom.BluetoothDeviceProperties} + */ + device: { + type: Object, + }, + + /** + * Enum used as an ID for specific UI elements. + * A BatteryType is passed between html and JS for + * certain UI elements to determine their state. + * + * @type {!BatteryType} + */ + BatteryType: { + type: Object, + value: BatteryType, + }, + }; + } + + /** + * Only show specific battery information if the device is + * Connected and there exists information for that device. + * + * @param {!chromeos.bluetoothConfig.mojom.BluetoothDeviceProperties} + * device + * @param {!BatteryType} batteryType + * @return {boolean} + * @protected + */ + shouldShowBatteryTypeInfo_(device, batteryType) { + if (device.connectionState !== + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kConnected || + !hasTrueWirelessImages(device)) { + return false; + } + + return getBatteryPercentage(device, batteryType) !== undefined; + } + + /** + * @param {!chromeos.bluetoothConfig.mojom.BluetoothDeviceProperties} + * device + * @return {boolean} + * @protected + */ + shouldShowNotConnectedInfo_(device) { + if (!hasTrueWirelessImages(device)) { + return false; + } + + return device.connectionState === + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kNotConnected || + device.connectionState === + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kConnecting; + } + + /** + * @param {!chromeos.bluetoothConfig.mojom.BluetoothDeviceProperties} + * device + * @param {!BatteryType} batteryType + * @return {string} + * @protected + */ + getBatteryTypeString_(device, batteryType) { + switch (batteryType) { + case BatteryType.LEFT_BUD: + return this.i18n('bluetoothTrueWirelessLeftBudLabel'); + case BatteryType.CASE: + return this.i18n('bluetoothTrueWirelessCaseLabel'); + case BatteryType.RIGHT_BUD: + return this.i18n('bluetoothTrueWirelessRightBudLabel'); + default: + assertNotReached(); + } + } + + /** + * @param {!chromeos.bluetoothConfig.mojom.BluetoothDeviceProperties} + * device + * @param {!BatteryType} batteryType + * @return {string} + * @private + */ + getImageSrc_(device, batteryType) { + switch (batteryType) { + case BatteryType.LEFT_BUD: + return this.device.imageInfo.trueWirelessImages.leftBudImageUrl.url; + case BatteryType.CASE: + return this.device.imageInfo.trueWirelessImages.caseImageUrl.url; + case BatteryType.RIGHT_BUD: + return this.device.imageInfo.trueWirelessImages.rightBudImageUrl.url; + default: + assertNotReached(); + } + } +} + +customElements.define( + SettingsBluetoothTrueWirelessImagesElement.is, + SettingsBluetoothTrueWirelessImagesElement);
diff --git a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js index eccebd7..460d270 100644 --- a/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js +++ b/chrome/browser/resources/settings/chromeos/os_languages_page/input_page.js
@@ -268,9 +268,8 @@ * @private */ hasOptionsPageInSettings_(id) { - return loadTimeData.getBoolean('imeOptionsInSettings') && - hasOptionsPageInSettings( - id, loadTimeData.getBoolean('allowPredictiveWriting')); + return hasOptionsPageInSettings( + id, loadTimeData.getBoolean('allowPredictiveWriting')); }, /**
diff --git a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.html b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.html index b279ea8..99fe2203 100644 --- a/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.html +++ b/chrome/browser/resources/settings/chromeos/os_people_page/account_manager.html
@@ -1,6 +1,7 @@ <style include="settings-shared iron-flex iron-flex-alignment"> :host { --add-account-margin-top: 16px; + --account-item-padding-size: 8px; } .account-manager-description {
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.gni b/chrome/browser/resources/settings/chromeos/os_settings.gni index 8ff389c..22ffea7 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.gni +++ b/chrome/browser/resources/settings/chromeos/os_settings.gni
@@ -227,6 +227,7 @@ "chrome/browser/resources/settings/chromeos/os_a11y_page/os_a11y_page_browser_proxy.html|OsA11yPageBrowserProxyImpl,OsA11yPageBrowserProxy", "chrome/browser/resources/settings/chromeos/os_a11y_page/tts_subpage_browser_proxy.html|TtsSubpageBrowserProxy,TtsSubpageBrowserProxyImpl", "chrome/browser/resources/settings/chromeos/os_a11y_page/switch_access_action_assignment_pane.html|getLabelForAssignment", + "chrome/browser/resources/settings/chromeos/os_bluetooth_page/os_bluetooth_devices_subpage_browser_proxy.html|OsBluetoothDevicesSubpageBrowserProxy, OsBluetoothDevicesSubpageBrowserProxyImpl", "chrome/browser/resources/settings/chromeos/os_languages_page/input_method_util.html|generateOptions,getFirstPartyInputMethodEngineId,getOptionLabelName,getOptionMenuItems,getOptionUiType,getOptionUrl,hasOptionsPageInSettings,isNumberValue,OPTION_DEFAULT,OptionType,UiType, isOptionLabelTranslated, getUntranslatedOptionLabelName", "chrome/browser/resources/settings/chromeos/os_languages_page/languages_metrics_proxy.html|LanguagesMetricsProxy, LanguagesMetricsProxyImpl, LanguagesPageInteraction, InputsShortcutReminderState", "chrome/browser/resources/settings/chromeos/os_people_page/fingerprint_browser_proxy.html|FingerprintInfo,FingerprintBrowserProxy,FingerprintResultType,FingerprintBrowserProxyImpl,FingerprintAttempt,FingerprintScan",
diff --git a/chrome/browser/resources/settings/chromeos/os_settings.js b/chrome/browser/resources/settings/chromeos/os_settings.js index 6138c2f8..92b7c20a 100644 --- a/chrome/browser/resources/settings/chromeos/os_settings.js +++ b/chrome/browser/resources/settings/chromeos/os_settings.js
@@ -70,6 +70,7 @@ import './os_apps_page/os_apps_page.js'; import './os_bluetooth_page/os_bluetooth_devices_subpage.js'; import './os_bluetooth_page/os_bluetooth_device_detail_subpage.js'; +import './os_bluetooth_page/os_bluetooth_true_wireless_images.js'; import './os_bluetooth_page/os_bluetooth_change_device_name_dialog.js'; import './os_bluetooth_page/os_bluetooth_pairing_dialog.js'; import './os_bluetooth_page/os_bluetooth_page.js';
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts index e041b7e4..d1ddd1a 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/clear_browsing_data_dialog.ts
@@ -38,6 +38,7 @@ import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../router.js'; import {ClearBrowsingDataBrowserProxy, ClearBrowsingDataBrowserProxyImpl, InstalledApp, UpdateSyncStateEvent} from './clear_browsing_data_browser_proxy.js'; +import {getTemplate} from './clear_browsing_data_dialog.html.js'; /** * InstalledAppsDialogActions enum. @@ -101,7 +102,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.ts b/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.ts index 5480e3b0..cde353c 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.ts +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/history_deletion_dialog.ts
@@ -14,6 +14,7 @@ import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './history_deletion_dialog.html.js'; export interface SettingsHistoryDeletionDialogElement { $: { @@ -27,7 +28,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } /** Click handler for the "OK" button. */
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.ts b/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.ts index edf1677a..da0c8ca 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.ts +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/installed_app_checkbox.ts
@@ -15,6 +15,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {InstalledApp} from './clear_browsing_data_browser_proxy.js'; +import {getTemplate} from './installed_app_checkbox.html.js'; class InstalledAppCheckboxElement extends PolymerElement { static get is() { @@ -22,7 +23,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/clear_browsing_data_dialog/passwords_deletion_dialog.ts b/chrome/browser/resources/settings/clear_browsing_data_dialog/passwords_deletion_dialog.ts index 5842519..b850e2d 100644 --- a/chrome/browser/resources/settings/clear_browsing_data_dialog/passwords_deletion_dialog.ts +++ b/chrome/browser/resources/settings/clear_browsing_data_dialog/passwords_deletion_dialog.ts
@@ -14,6 +14,7 @@ import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './passwords_deletion_dialog.html.js'; export interface SettingsPasswordsDeletionDialogElement { $: { @@ -27,7 +28,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } /** Click handler for the "OK" button. */
diff --git a/chrome/browser/resources/settings/controls/controlled_button.ts b/chrome/browser/resources/settings/controls/controlled_button.ts index 188761ae..a8d7dbc 100644 --- a/chrome/browser/resources/settings/controls/controlled_button.ts +++ b/chrome/browser/resources/settings/controls/controlled_button.ts
@@ -8,6 +8,7 @@ import '../settings_shared_css.js'; import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './controlled_button.html.js'; import {CrPolicyPrefMixin} from './cr_policy_pref_mixin.js'; import {PrefControlMixin} from './pref_control_mixin.js'; @@ -21,7 +22,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/controls/controlled_radio_button.ts b/chrome/browser/resources/settings/controls/controlled_radio_button.ts index f92bc01..4b542b3 100644 --- a/chrome/browser/resources/settings/controls/controlled_radio_button.ts +++ b/chrome/browser/resources/settings/controls/controlled_radio_button.ts
@@ -13,6 +13,7 @@ import {prefToString} from '../prefs/pref_util.js'; +import {getTemplate} from './controlled_radio_button.html.js'; import {PrefControlMixin, PrefControlMixinInterface} from './pref_control_mixin.js'; const ControlledRadioButtonElementBase = @@ -28,7 +29,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get observers() {
diff --git a/chrome/browser/resources/settings/controls/extension_controlled_indicator.ts b/chrome/browser/resources/settings/controls/extension_controlled_indicator.ts index a42fb76a32..704d2bc 100644 --- a/chrome/browser/resources/settings/controls/extension_controlled_indicator.ts +++ b/chrome/browser/resources/settings/controls/extension_controlled_indicator.ts
@@ -12,6 +12,8 @@ import {ExtensionControlBrowserProxyImpl} from '../extension_control_browser_proxy.js'; +import {getTemplate} from './extension_controlled_indicator.html.js'; + const ExtensionControlledIndicatorElementBase = I18nMixin(PolymerElement); export class ExtensionControlledIndicatorElement extends @@ -21,7 +23,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/controls/password_prompt_dialog.ts b/chrome/browser/resources/settings/controls/password_prompt_dialog.ts index f816b95..27737c4 100644 --- a/chrome/browser/resources/settings/controls/password_prompt_dialog.ts +++ b/chrome/browser/resources/settings/controls/password_prompt_dialog.ts
@@ -28,6 +28,7 @@ import {CrDialogElement} from '//resources/cr_elements/cr_dialog/cr_dialog.m.js'; import {CrInputElement} from '//resources/cr_elements/cr_input/cr_input.m.js'; import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './password_prompt_dialog.html.js'; interface SettingsPasswordPromptDialogElement { $: { @@ -41,7 +42,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/controls/pref_control_mixin.ts b/chrome/browser/resources/settings/controls/pref_control_mixin.ts index 0db6652b..163e569 100644 --- a/chrome/browser/resources/settings/controls/pref_control_mixin.ts +++ b/chrome/browser/resources/settings/controls/pref_control_mixin.ts
@@ -41,12 +41,9 @@ private validatePref_() { CrSettingsPrefs.initialized.then(() => { if (this.pref === undefined) { - let error = 'Pref not found for element ' + this.tagName; - if (this.id) { - error += '#' + this.id; - } - error += ' in ' + (this.getRootNode() as ShadowRoot).host.tagName; - console.error(error); + console.error(this.getErrorInfo('not found')); + } else if (typeof this.pref === 'string') { + console.error(this.getErrorInfo('incorrect type string')); } else if ( this.pref.enforcement === chrome.settingsPrivate.Enforcement.PARENT_SUPERVISED) { @@ -55,6 +52,19 @@ } }); } + + /** + * Produce an error message with additional information about the + * element and host causing the error. + */ + private getErrorInfo(message: string): string { + let error = `Pref error [${message}] for element ${this.tagName}`; + if (this.id) { + error += `#${this.id}`; + } + error += ` in ${(this.getRootNode() as ShadowRoot).host.tagName}`; + return error; + } } return PrefControlMixin;
diff --git a/chrome/browser/resources/settings/controls/settings_checkbox.ts b/chrome/browser/resources/settings/controls/settings_checkbox.ts index 146ca939..35c1955 100644 --- a/chrome/browser/resources/settings/controls/settings_checkbox.ts +++ b/chrome/browser/resources/settings/controls/settings_checkbox.ts
@@ -14,6 +14,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SettingsBooleanControlMixin} from './settings_boolean_control_mixin.js'; +import {getTemplate} from './settings_checkbox.html.js'; export interface SettingsCheckboxElement { $: { @@ -30,7 +31,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/controls/settings_dropdown_menu.ts b/chrome/browser/resources/settings/controls/settings_dropdown_menu.ts index e789fc36..033ef6c4 100644 --- a/chrome/browser/resources/settings/controls/settings_dropdown_menu.ts +++ b/chrome/browser/resources/settings/controls/settings_dropdown_menu.ts
@@ -23,6 +23,7 @@ import {CrPolicyPrefMixin} from './cr_policy_pref_mixin.js'; import {PrefControlMixin} from './pref_control_mixin.js'; +import {getTemplate} from './settings_dropdown_menu.html.js'; /** * The |name| is shown in the gui. The |value| us use to set or compare with @@ -51,7 +52,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/controls/settings_radio_group.ts b/chrome/browser/resources/settings/controls/settings_radio_group.ts index 78988ed..5bb94d8 100644 --- a/chrome/browser/resources/settings/controls/settings_radio_group.ts +++ b/chrome/browser/resources/settings/controls/settings_radio_group.ts
@@ -21,6 +21,7 @@ import {prefToString, stringToPrefValue} from '../prefs/pref_util.js'; import {PrefControlMixin} from './pref_control_mixin.js'; +import {getTemplate} from './settings_radio_group.html.js'; const SettingsRadioGroupElementBase = PrefControlMixin(PolymerElement); @@ -30,7 +31,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/controls/settings_slider.ts b/chrome/browser/resources/settings/controls/settings_slider.ts index 8ba665a..57cf47e 100644 --- a/chrome/browser/resources/settings/controls/settings_slider.ts +++ b/chrome/browser/resources/settings/controls/settings_slider.ts
@@ -18,6 +18,7 @@ import {loadTimeData} from '../i18n_setup.js'; import {CrPolicyPrefMixin} from './cr_policy_pref_mixin.js'; +import {getTemplate} from './settings_slider.html.js'; export interface SettingsSliderElement { $: { @@ -33,7 +34,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/controls/settings_textarea.ts b/chrome/browser/resources/settings/controls/settings_textarea.ts index c15280a..ecbc4848 100644 --- a/chrome/browser/resources/settings/controls/settings_textarea.ts +++ b/chrome/browser/resources/settings/controls/settings_textarea.ts
@@ -11,6 +11,7 @@ import '//resources/cr_elements/cr_input/cr_input_style_css.m.js'; import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './settings_textarea.html.js'; export interface SettingsTextareaElement { $: { @@ -25,7 +26,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/controls/settings_toggle_button.ts b/chrome/browser/resources/settings/controls/settings_toggle_button.ts index a55ae84..b20e9de 100644 --- a/chrome/browser/resources/settings/controls/settings_toggle_button.ts +++ b/chrome/browser/resources/settings/controls/settings_toggle_button.ts
@@ -16,9 +16,11 @@ import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; // <if expr="chromeos"> import {sanitizeInnerHtml} from 'chrome://resources/js/parse_html_subset.m.js'; + // </if> import {SettingsBooleanControlMixin} from './settings_boolean_control_mixin.js'; +import {getTemplate} from './settings_toggle_button.html.js'; export interface SettingsToggleButtonElement { @@ -38,7 +40,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/default_browser_page/default_browser_page.ts b/chrome/browser/resources/settings/default_browser_page/default_browser_page.ts index 31ad015..8bb9802 100644 --- a/chrome/browser/resources/settings/default_browser_page/default_browser_page.ts +++ b/chrome/browser/resources/settings/default_browser_page/default_browser_page.ts
@@ -17,6 +17,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {DefaultBrowserBrowserProxy, DefaultBrowserBrowserProxyImpl, DefaultBrowserInfo} from './default_browser_browser_proxy.js'; +import {getTemplate} from './default_browser_page.html.js'; const SettingsDefaultBrowserPageElementBase = WebUIListenerMixin(PolymerElement); @@ -28,7 +29,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/downloads_page/downloads_page.ts b/chrome/browser/resources/settings/downloads_page/downloads_page.ts index 914313da..bfa3796 100644 --- a/chrome/browser/resources/settings/downloads_page/downloads_page.ts +++ b/chrome/browser/resources/settings/downloads_page/downloads_page.ts
@@ -22,6 +22,7 @@ import {PrefsMixin} from '../prefs/prefs_mixin.js'; import {DownloadsBrowserProxy, DownloadsBrowserProxyImpl} from './downloads_browser_proxy.js'; +import {getTemplate} from './downloads_page.html.js'; type AccountInfo = { linked: boolean, @@ -39,7 +40,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.ts b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.ts index befc745..877253f6 100644 --- a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.ts +++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_application_item.ts
@@ -39,6 +39,7 @@ import {assertNotReached} from 'chrome://resources/js/assert.m.js'; import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './incompatible_application_item.html.js'; import {ActionTypes, IncompatibleApplicationsBrowserProxy, IncompatibleApplicationsBrowserProxyImpl} from './incompatible_applications_browser_proxy.js'; @@ -51,7 +52,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.ts b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.ts index 8de197f..b2e8d67d 100644 --- a/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.ts +++ b/chrome/browser/resources/settings/incompatible_applications_page/incompatible_applications_page.ts
@@ -22,6 +22,7 @@ import {loadTimeData} from '../i18n_setup.js'; import {IncompatibleApplication, IncompatibleApplicationsBrowserProxyImpl} from './incompatible_applications_browser_proxy.js'; +import {getTemplate} from './incompatible_applications_page.html.js'; const SettingsIncompatibleApplicationsPageElementBase = WebUIListenerMixin(PolymerElement); @@ -33,7 +34,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/languages_page/add_languages_dialog.ts b/chrome/browser/resources/settings/languages_page/add_languages_dialog.ts index 326c809d..a82360f 100644 --- a/chrome/browser/resources/settings/languages_page/add_languages_dialog.ts +++ b/chrome/browser/resources/settings/languages_page/add_languages_dialog.ts
@@ -20,6 +20,7 @@ import {CrSearchFieldElement} from 'chrome://resources/cr_elements/cr_search_field/cr_search_field.js'; import {FindShortcutMixin, FindShortcutMixinInterface} from 'chrome://resources/cr_elements/find_shortcut_mixin.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './add_languages_dialog.html.js'; export interface SettingsAddLanguagesDialogElement { $: { @@ -51,7 +52,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/languages_page/edit_dictionary_page.ts b/chrome/browser/resources/settings/languages_page/edit_dictionary_page.ts index 484f645..06ea03b 100644 --- a/chrome/browser/resources/settings/languages_page/edit_dictionary_page.ts +++ b/chrome/browser/resources/settings/languages_page/edit_dictionary_page.ts
@@ -27,6 +27,7 @@ import {routes} from '../route.js'; import {Route} from '../router.js'; +import {getTemplate} from './edit_dictionary_page.html.js'; import {LanguagesBrowserProxyImpl} from './languages_browser_proxy.js'; // Max valid word size defined in @@ -53,7 +54,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/languages_page/languages_page.ts b/chrome/browser/resources/settings/languages_page/languages_page.ts index 2107eba..9a1adaf 100644 --- a/chrome/browser/resources/settings/languages_page/languages_page.ts +++ b/chrome/browser/resources/settings/languages_page/languages_page.ts
@@ -45,6 +45,7 @@ import {routes} from '../route.js'; import {Router} from '../router.js'; +import {getTemplate} from './languages_page.html.js'; import {LanguageSettingsMetricsProxy, LanguageSettingsMetricsProxyImpl, LanguageSettingsPageImpressionType} from './languages_settings_metrics_proxy.js'; import {LanguageHelper, LanguagesModel, LanguageState, SpellCheckLanguageState} from './languages_types.js'; @@ -60,7 +61,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/languages_page/languages_subpage.ts b/chrome/browser/resources/settings/languages_page/languages_subpage.ts index ab68168..0e0a95b 100644 --- a/chrome/browser/resources/settings/languages_page/languages_subpage.ts +++ b/chrome/browser/resources/settings/languages_page/languages_subpage.ts
@@ -50,6 +50,7 @@ import {RelaunchMixin, RestartType} from '../relaunch_mixin.js'; import {LanguageSettingsActionType, LanguageSettingsMetricsProxy, LanguageSettingsMetricsProxyImpl, LanguageSettingsPageImpressionType} from './languages_settings_metrics_proxy.js'; +import {getTemplate} from './languages_subpage.html.js'; import {LanguageHelper, LanguagesModel, LanguageState} from './languages_types.js'; /** @@ -615,7 +616,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } }
diff --git a/chrome/browser/resources/settings/on_startup_page/on_startup_page.ts b/chrome/browser/resources/settings/on_startup_page/on_startup_page.ts index c4dd5d4..1c184ad 100644 --- a/chrome/browser/resources/settings/on_startup_page/on_startup_page.ts +++ b/chrome/browser/resources/settings/on_startup_page/on_startup_page.ts
@@ -19,6 +19,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {NtpExtension, OnStartupBrowserProxyImpl} from './on_startup_browser_proxy.js'; +import {getTemplate} from './on_startup_page.html.js'; /** Enum values for the 'session.restore_on_startup' preference. */ @@ -38,7 +39,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.ts b/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.ts index c6544032..4383f96 100644 --- a/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.ts +++ b/chrome/browser/resources/settings/on_startup_page/startup_url_dialog.ts
@@ -14,6 +14,7 @@ import {loadTimeData} from '../i18n_setup.js'; +import {getTemplate} from './startup_url_dialog.html.js'; import {StartupPageInfo, StartupUrlsPageBrowserProxy, StartupUrlsPageBrowserProxyImpl} from './startup_urls_page_browser_proxy.js'; @@ -46,7 +47,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_url_entry.ts b/chrome/browser/resources/settings/on_startup_page/startup_url_entry.ts index 1d3d8b9..322780d 100644 --- a/chrome/browser/resources/settings/on_startup_page/startup_url_entry.ts +++ b/chrome/browser/resources/settings/on_startup_page/startup_url_entry.ts
@@ -20,6 +20,7 @@ import {assert} from 'chrome://resources/js/assert.m.js'; import {FocusRowBehavior} from 'chrome://resources/js/cr/ui/focus_row_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './startup_url_entry.html.js'; import {StartupPageInfo, StartupUrlsPageBrowserProxyImpl} from './startup_urls_page_browser_proxy.js'; @@ -40,7 +41,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.ts b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.ts index 17c428bf..8ccf93d 100644 --- a/chrome/browser/resources/settings/on_startup_page/startup_urls_page.ts +++ b/chrome/browser/resources/settings/on_startup_page/startup_urls_page.ts
@@ -22,6 +22,7 @@ import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {EDIT_STARTUP_URL_EVENT} from './startup_url_entry.js'; +import {getTemplate} from './startup_urls_page.html.js'; import {StartupPageInfo, StartupUrlsPageBrowserProxy, StartupUrlsPageBrowserProxyImpl} from './startup_urls_page_browser_proxy.js'; @@ -39,7 +40,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/people_page/import_data_dialog.ts b/chrome/browser/resources/settings/people_page/import_data_dialog.ts index 130c7916..bbf0572c 100644 --- a/chrome/browser/resources/settings/people_page/import_data_dialog.ts +++ b/chrome/browser/resources/settings/people_page/import_data_dialog.ts
@@ -27,6 +27,7 @@ import {PrefsMixin} from '../prefs/prefs_mixin.js'; import {BrowserProfile, ImportDataBrowserProxy, ImportDataBrowserProxyImpl, ImportDataStatus} from './import_data_browser_proxy.js'; +import {getTemplate} from './import_data_dialog.html.js'; export interface SettingsImportDataDialogElement { $: { @@ -49,7 +50,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/people_page/manage_profile.ts b/chrome/browser/resources/settings/people_page/manage_profile.ts index bd21173..8357a5f 100644 --- a/chrome/browser/resources/settings/people_page/manage_profile.ts +++ b/chrome/browser/resources/settings/people_page/manage_profile.ts
@@ -25,6 +25,7 @@ import {routes} from '../route.js'; import {RouteObserverMixin, RouteObserverMixinInterface, Router} from '../router.js'; +import {getTemplate} from './manage_profile.html.js'; import {ManageProfileBrowserProxy, ManageProfileBrowserProxyImpl, ProfileShortcutStatus} from './manage_profile_browser_proxy.js'; import {SyncStatus} from './sync_browser_proxy.js'; @@ -47,7 +48,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/people_page/people_page.ts b/chrome/browser/resources/settings/people_page/people_page.ts index b00a4a0..6c7a283d 100644 --- a/chrome/browser/resources/settings/people_page/people_page.ts +++ b/chrome/browser/resources/settings/people_page/people_page.ts
@@ -43,6 +43,8 @@ // <if expr="chromeos"> import {AccountManagerBrowserProxyImpl} from './account_manager_browser_proxy.js'; // </if> + +import {getTemplate} from './people_page.html.js'; import {ProfileInfo, ProfileInfoBrowserProxyImpl} from './profile_info_browser_proxy.js'; import {StoredAccount, SyncBrowserProxy, SyncBrowserProxyImpl, SyncStatus} from './sync_browser_proxy.js'; @@ -67,7 +69,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/people_page/signout_dialog.ts b/chrome/browser/resources/settings/people_page/signout_dialog.ts index fcb60ff..57665610 100644 --- a/chrome/browser/resources/settings/people_page/signout_dialog.ts +++ b/chrome/browser/resources/settings/people_page/signout_dialog.ts
@@ -23,6 +23,7 @@ import {loadTimeData} from '../i18n_setup.js'; import {ProfileInfoBrowserProxyImpl} from './profile_info_browser_proxy.js'; +import {getTemplate} from './signout_dialog.html.js'; import {SyncBrowserProxyImpl, SyncStatus} from './sync_browser_proxy.js'; export interface SettingsSignoutDialogElement { @@ -41,7 +42,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/people_page/sync_account_control.ts b/chrome/browser/resources/settings/people_page/sync_account_control.ts index 36d1ef6..4ca4718 100644 --- a/chrome/browser/resources/settings/people_page/sync_account_control.ts +++ b/chrome/browser/resources/settings/people_page/sync_account_control.ts
@@ -27,6 +27,7 @@ import {PrefsMixin} from '../prefs/prefs_mixin.js'; import {Route, Router} from '../router.js'; +import {getTemplate} from './sync_account_control.html.js'; import {StatusAction, StoredAccount, SyncBrowserProxy, SyncBrowserProxyImpl, SyncStatus} from './sync_browser_proxy.js'; export const MAX_SIGNIN_PROMO_IMPRESSION: number = 10; @@ -47,7 +48,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/people_page/sync_controls.ts b/chrome/browser/resources/settings/people_page/sync_controls.ts index 0176a54..019a0fd 100644 --- a/chrome/browser/resources/settings/people_page/sync_controls.ts +++ b/chrome/browser/resources/settings/people_page/sync_controls.ts
@@ -22,6 +22,7 @@ import {Route, Router} from '../router.js'; import {StatusAction, SyncBrowserProxy, SyncBrowserProxyImpl, SyncPrefs, syncPrefsIndividualDataTypes, SyncStatus} from './sync_browser_proxy.js'; +import {getTemplate} from './sync_controls.html.js'; /** * Names of the radio buttons which allow the user to choose their data sync @@ -46,7 +47,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/people_page/sync_encryption_options.ts b/chrome/browser/resources/settings/people_page/sync_encryption_options.ts index 480e831..4af4861 100644 --- a/chrome/browser/resources/settings/people_page/sync_encryption_options.ts +++ b/chrome/browser/resources/settings/people_page/sync_encryption_options.ts
@@ -11,7 +11,6 @@ import '../settings_vars_css.js'; import {CrInputElement} from '//resources/cr_elements/cr_input/cr_input.m.js'; - // <if expr="chromeos"> import {CrRadioGroupElement} from '//resources/cr_elements/cr_radio_group/cr_radio_group.m.js'; // </if> @@ -20,6 +19,7 @@ import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SyncBrowserProxyImpl, SyncPrefs, SyncStatus} from './sync_browser_proxy.js'; +import {getTemplate} from './sync_encryption_options.html.js'; /** * Names of the radio buttons which allow the user to choose their encryption @@ -36,7 +36,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/people_page/sync_page.ts b/chrome/browser/resources/settings/people_page/sync_page.ts index 17a26c33..7eed630c 100644 --- a/chrome/browser/resources/settings/people_page/sync_page.ts +++ b/chrome/browser/resources/settings/people_page/sync_page.ts
@@ -19,9 +19,9 @@ import '../privacy_page/personalization_options.js'; import '../settings_shared_css.js'; import '../settings_vars_css.js'; - // <if expr="not chromeos"> import '//resources/cr_elements/cr_toast/cr_toast.js'; + // </if> import {CrDialogElement} from '//resources/cr_elements/cr_dialog/cr_dialog.m.js'; @@ -29,7 +29,6 @@ import {assert, assertNotReached} from '//resources/js/assert.m.js'; import {focusWithoutInk} from '//resources/js/cr/ui/focus_without_ink.m.js'; import {WebUIListenerMixin, WebUIListenerMixinInterface} from '//resources/js/web_ui_listener_mixin.js'; - import {IronCollapseElement} from '//resources/polymer/v3_0/iron-collapse/iron-collapse.js'; import {flush, html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {I18nMixin, I18nMixinInterface} from 'chrome://resources/js/i18n_mixin.js'; @@ -46,6 +45,8 @@ import {SettingsSyncEncryptionOptionsElement} from './sync_encryption_options.js'; // </if> +import {getTemplate} from './sync_page.html.js'; + // TODO(rbpotter): Remove this typedef when this file is no longer needed by OS // Settings. type SyncRoutes = { @@ -86,7 +87,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts index 5cfdb0bc..94226bc 100644 --- a/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts +++ b/chrome/browser/resources/settings/privacy_page/collapse_radio_button.ts
@@ -11,6 +11,7 @@ import {CrExpandButtonElement} from 'chrome://resources/cr_elements/cr_expand_button/cr_expand_button.m.js'; import {CrRadioButtonBehavior} from 'chrome://resources/cr_elements/cr_radio_button/cr_radio_button_behavior.m.js'; import {html, mixinBehaviors, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './collapse_radio_button.html.js'; export interface SettingsCollapseRadioButtonElement { $: { @@ -28,7 +29,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/cookies_page.ts b/chrome/browser/resources/settings/privacy_page/cookies_page.ts index a9fea35e..e61349a6 100644 --- a/chrome/browser/resources/settings/privacy_page/cookies_page.ts +++ b/chrome/browser/resources/settings/privacy_page/cookies_page.ts
@@ -37,6 +37,7 @@ import {CookiePrimarySetting} from '../site_settings/site_settings_prefs_browser_proxy.js'; import {SettingsCollapseRadioButtonElement} from './collapse_radio_button.js'; +import {getTemplate} from './cookies_page.html.js'; /** * Must be kept in sync with the C++ enum of the same name (see @@ -77,7 +78,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/disable_safebrowsing_dialog.ts b/chrome/browser/resources/settings/privacy_page/disable_safebrowsing_dialog.ts index 5140fbb5..a34a5e4 100644 --- a/chrome/browser/resources/settings/privacy_page/disable_safebrowsing_dialog.ts +++ b/chrome/browser/resources/settings/privacy_page/disable_safebrowsing_dialog.ts
@@ -12,6 +12,7 @@ import {CrButtonElement} from 'chrome://resources/cr_elements/cr_button/cr_button.m.js'; import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './disable_safebrowsing_dialog.html.js'; export interface SettingsDisableSafebrowsingDialogElement { $: { @@ -27,7 +28,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } connectedCallback() {
diff --git a/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts b/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts index 1b4f13f..2a62ac9d 100644 --- a/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts +++ b/chrome/browser/resources/settings/privacy_page/do_not_track_toggle.ts
@@ -13,6 +13,8 @@ import {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js'; import {MetricsBrowserProxyImpl, PrivacyElementInteractions} from '../metrics_browser_proxy.js'; +import {getTemplate} from './do_not_track_toggle.html.js'; + export interface SettingsDoNotTrackToggleElement { $: { toggle: SettingsToggleButtonElement, @@ -25,7 +27,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/personalization_options.ts b/chrome/browser/resources/settings/privacy_page/personalization_options.ts index dc12b24..1dbea60 100644 --- a/chrome/browser/resources/settings/privacy_page/personalization_options.ts +++ b/chrome/browser/resources/settings/privacy_page/personalization_options.ts
@@ -18,6 +18,7 @@ import '../settings_shared_css.js'; // <if expr="not chromeos_ash"> import '//resources/cr_elements/cr_toast/cr_toast.js'; + // </if> import {CrToastElement} from '//resources/cr_elements/cr_toast/cr_toast.js'; @@ -32,6 +33,7 @@ import {PrefsMixin} from '../prefs/prefs_mixin.js'; import {RelaunchMixin, RestartType} from '../relaunch_mixin.js'; +import {getTemplate} from './personalization_options.html.js'; import {MetricsReporting, PrivacyPageBrowserProxy, PrivacyPageBrowserProxyImpl} from './privacy_page_browser_proxy.js'; @@ -54,7 +56,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_page.ts b/chrome/browser/resources/settings/privacy_page/privacy_page.ts index 161f9af9..f0f1e82 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_page.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_page.ts
@@ -41,6 +41,7 @@ import {ChooserType, ContentSettingsTypes, NotificationSetting} from '../site_settings/constants.js'; import {SiteSettingsPrefsBrowserProxyImpl} from '../site_settings/site_settings_prefs_browser_proxy.js'; +import {getTemplate} from './privacy_page.html.js'; import {PrivacyPageBrowserProxy, PrivacyPageBrowserProxyImpl} from './privacy_page_browser_proxy.js'; type BlockAutoplayStatus = { @@ -75,7 +76,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_clear_on_exit_fragment.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_clear_on_exit_fragment.ts index 59dee22..6fb2a1f 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_clear_on_exit_fragment.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_clear_on_exit_fragment.ts
@@ -13,6 +13,7 @@ import './privacy_review_fragment_shared_css.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './privacy_review_clear_on_exit_fragment.html.js'; export class PrivacyReviewClearOnExitFragmentElement extends PolymerElement { static get is() { @@ -20,7 +21,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_completion_fragment.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_completion_fragment.ts index bdd4e4b..5bcdd855 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_completion_fragment.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_completion_fragment.ts
@@ -21,6 +21,8 @@ import {OpenWindowProxyImpl} from '../../open_window_proxy.js'; import {SyncBrowserProxyImpl, SyncStatus} from '../../people_page/sync_browser_proxy.js'; +import {getTemplate} from './privacy_review_completion_fragment.html.js'; + const PrivacyReviewCompletionFragmentElementBase = WebUIListenerMixin(PolymerElement); @@ -31,7 +33,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_completion_link_row.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_completion_link_row.ts index 28330d0d..97fbf9f 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_completion_link_row.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_completion_link_row.ts
@@ -13,6 +13,7 @@ import 'chrome://resources/cr_elements/shared_vars_css.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './privacy_review_completion_link_row.html.js'; export class PrivacyReviewCompletionLinkRowElement extends PolymerElement { static get is() { @@ -20,7 +21,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.ts index 6f8f0f77..701c2938 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_cookies_fragment.ts
@@ -19,6 +19,8 @@ import {PrefsMixin} from '../../prefs/prefs_mixin.js'; import {CookiePrimarySetting} from '../../site_settings/site_settings_prefs_browser_proxy.js'; +import {getTemplate} from './privacy_review_cookies_fragment.html.js'; + const PrivacyReviewCookiesFragmentBase = PrefsMixin(PolymerElement); export class PrivacyReviewCookiesFragmentElement extends @@ -28,7 +30,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_description_item.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_description_item.ts index 577a5d3b..4d3e4669 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_description_item.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_description_item.ts
@@ -12,6 +12,7 @@ import '../../settings_shared_css.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './privacy_review_description_item.html.js'; export class PrivacyReviewDescriptionItemElement extends PolymerElement { static get is() { @@ -19,7 +20,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_history_sync_fragment.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_history_sync_fragment.ts index d02b842..2c9b343 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_history_sync_fragment.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_history_sync_fragment.ts
@@ -24,6 +24,7 @@ import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../../router.js'; import {PrivacyReviewStep} from './constants.js'; +import {getTemplate} from './privacy_review_history_sync_fragment.html.js'; export interface PrivacyReviewHistorySyncFragmentElement { $: { @@ -44,7 +45,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_msbb_fragment.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_msbb_fragment.ts index 63169902..1756e6e 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_msbb_fragment.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_msbb_fragment.ts
@@ -17,6 +17,8 @@ import {MetricsBrowserProxy, MetricsBrowserProxyImpl, PrivacyGuideSettingsStates} from '../../metrics_browser_proxy.js'; import {PrefsMixin} from '../../prefs/prefs_mixin.js'; +import {getTemplate} from './privacy_review_msbb_fragment.html.js'; + const PrivacyReviewMsbbFragmentBase = PrefsMixin(PolymerElement); export class PrivacyReviewMsbbFragmentElement extends @@ -26,7 +28,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_page.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_page.ts index cba5970..228cb62 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_page.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_page.ts
@@ -38,6 +38,7 @@ import {CookiePrimarySetting} from '../../site_settings/site_settings_prefs_browser_proxy.js'; import {PrivacyReviewStep} from './constants.js'; +import {getTemplate} from './privacy_review_page.html.js'; import {StepIndicatorModel} from './step_indicator.js'; interface PrivacyReviewStepComponents { @@ -66,7 +67,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.ts index 75c5101b..f4b08c1 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_safe_browsing_fragment.ts
@@ -19,6 +19,8 @@ import {PrefsMixin} from '../../prefs/prefs_mixin.js'; import {SafeBrowsingSetting} from '../../privacy_page/security_page.js'; +import {getTemplate} from './privacy_review_safe_browsing_fragment.html.js'; + const PrivacyReviewSafeBrowsingFragmentBase = PrefsMixin(PolymerElement); export class PrivacyReviewSafeBrowsingFragmentElement extends @@ -28,7 +30,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_welcome_fragment.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_welcome_fragment.ts index e134c160..c1a71a3 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_welcome_fragment.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review/privacy_review_welcome_fragment.ts
@@ -11,6 +11,7 @@ import './privacy_review_fragment_shared_css.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './privacy_review_welcome_fragment.html.js'; export interface PrivacyReviewWelcomeFragmentElement { $: { @@ -24,7 +25,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } private onStartButtonClick_(e: Event) {
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review/step_indicator.ts b/chrome/browser/resources/settings/privacy_page/privacy_review/step_indicator.ts index 75a84191..2c58039 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review/step_indicator.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review/step_indicator.ts
@@ -9,6 +9,7 @@ */ import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './step_indicator.html.js'; const StepIndicatorBase = I18nMixin(PolymerElement); @@ -67,7 +68,7 @@ static get template() { - return html`{__html_template__}`; + return getTemplate(); } }
diff --git a/chrome/browser/resources/settings/privacy_page/privacy_review_promo.ts b/chrome/browser/resources/settings/privacy_page/privacy_review_promo.ts index bc866f7..2bff5bd 100644 --- a/chrome/browser/resources/settings/privacy_page/privacy_review_promo.ts +++ b/chrome/browser/resources/settings/privacy_page/privacy_review_promo.ts
@@ -14,6 +14,8 @@ import {routes} from '../route.js'; import {Router} from '../router.js'; +import {getTemplate} from './privacy_review_promo.html.js'; + const PrivacyReviewPromoElementBase = PrefsMixin(PolymerElement); export class PrivacyReviewPromoElement extends PrivacyReviewPromoElementBase { @@ -22,7 +24,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/secure_dns.ts b/chrome/browser/resources/settings/privacy_page/secure_dns.ts index d98d1d9..1801d14 100644 --- a/chrome/browser/resources/settings/privacy_page/secure_dns.ts +++ b/chrome/browser/resources/settings/privacy_page/secure_dns.ts
@@ -32,6 +32,7 @@ import {PrefsMixin} from '../prefs/prefs_mixin.js'; import {PrivacyPageBrowserProxy, PrivacyPageBrowserProxyImpl, ResolverOption, SecureDnsMode, SecureDnsSetting, SecureDnsUiManagementMode} from './privacy_page_browser_proxy.js'; +import {getTemplate} from './secure_dns.html.js'; import {SecureDnsInputElement} from './secure_dns_input.js'; export interface SettingsSecureDnsElement { @@ -53,7 +54,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/secure_dns_input.ts b/chrome/browser/resources/settings/privacy_page/secure_dns_input.ts index 1bdafefd..6136577d 100644 --- a/chrome/browser/resources/settings/privacy_page/secure_dns_input.ts +++ b/chrome/browser/resources/settings/privacy_page/secure_dns_input.ts
@@ -15,6 +15,7 @@ import {loadTimeData} from '../i18n_setup.js'; import {PrivacyPageBrowserProxy, PrivacyPageBrowserProxyImpl} from './privacy_page_browser_proxy.js'; +import {getTemplate} from './secure_dns_input.html.js'; export interface SecureDnsInputElement { $: { @@ -28,7 +29,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts index 9c0bb306..96cd605 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts +++ b/chrome/browser/resources/settings/privacy_page/security_keys_bio_enroll_dialog.ts
@@ -31,6 +31,7 @@ import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js'; import {IronListElement} from 'chrome://resources/polymer/v3_0/iron-list/iron-list.js'; import {afterNextRender, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './security_keys_bio_enroll_dialog.html.js'; import {Ctap2Status, Enrollment, EnrollmentResponse, SampleResponse, SampleStatus, SecurityKeysBioEnrollProxy, SecurityKeysBioEnrollProxyImpl,} from './security_keys_browser_proxy.js'; import {SettingsSecurityKeysPinFieldElement} from './security_keys_pin_field.js'; @@ -68,7 +69,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.ts b/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.ts index 21a3d03..3d19456 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.ts +++ b/chrome/browser/resources/settings/privacy_page/security_keys_credential_management_dialog.ts
@@ -29,6 +29,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Credential, SecurityKeysCredentialBrowserProxy, SecurityKeysCredentialBrowserProxyImpl, StartCredentialManagementResponse} from './security_keys_browser_proxy.js'; +import {getTemplate} from './security_keys_credential_management_dialog.html.js'; import {SettingsSecurityKeysPinFieldElement} from './security_keys_pin_field.js'; export enum CredentialManagementDialogPage { @@ -69,7 +70,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_phones_dialog.ts b/chrome/browser/resources/settings/privacy_page/security_keys_phones_dialog.ts index afb65e6..7a8d010 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_phones_dialog.ts +++ b/chrome/browser/resources/settings/privacy_page/security_keys_phones_dialog.ts
@@ -14,7 +14,9 @@ import {CrDialogElement} from 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js'; import {CrInputElement} from 'chrome://resources/cr_elements/cr_input/cr_input.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + import {SecurityKeysPhonesBrowserProxy, SecurityKeysPhonesBrowserProxyImpl} from './security_keys_browser_proxy.js'; +import {getTemplate} from './security_keys_phones_dialog.html.js'; export interface SecurityKeysPhonesDialog { $: { @@ -30,7 +32,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_phones_list.ts b/chrome/browser/resources/settings/privacy_page/security_keys_phones_list.ts index 4bb44057..b625e8a 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_phones_list.ts +++ b/chrome/browser/resources/settings/privacy_page/security_keys_phones_list.ts
@@ -13,7 +13,9 @@ import {AnchorAlignment} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; + import {SecurityKeysPhone} from './security_keys_browser_proxy.js'; +import {getTemplate} from './security_keys_phones_list.html.js'; class SecurityKeysPhonesListElement extends PolymerElement { static get is() { @@ -21,7 +23,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_phones_subpage.ts b/chrome/browser/resources/settings/privacy_page/security_keys_phones_subpage.ts index 5459569..44b998d2 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_phones_subpage.ts +++ b/chrome/browser/resources/settings/privacy_page/security_keys_phones_subpage.ts
@@ -12,6 +12,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SecurityKeysPhone, SecurityKeysPhonesBrowserProxy, SecurityKeysPhonesBrowserProxyImpl, SecurityKeysPhonesList} from './security_keys_browser_proxy.js'; +import {getTemplate} from './security_keys_phones_subpage.html.js'; declare global { interface HTMLElementEventMap { @@ -26,7 +27,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } private syncedPhones_: Array<SecurityKeysPhone>;
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.ts b/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.ts index ee8ef07d..59f2b24 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.ts +++ b/chrome/browser/resources/settings/privacy_page/security_keys_pin_field.ts
@@ -16,6 +16,7 @@ import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {IronA11yAnnouncer} from 'chrome://resources/polymer/v3_0/iron-a11y-announcer/iron-a11y-announcer.js'; import {afterNextRender, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './security_keys_pin_field.html.js'; /** * A function that submits a PIN to a security key. It returns a Promise which @@ -39,7 +40,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.ts b/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.ts index 14611793..ff84673 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.ts +++ b/chrome/browser/resources/settings/privacy_page/security_keys_reset_dialog.ts
@@ -19,6 +19,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SecurityKeysResetBrowserProxy, SecurityKeysResetBrowserProxyImpl} from './security_keys_browser_proxy.js'; +import {getTemplate} from './security_keys_reset_dialog.html.js'; export enum ResetDialogPage { INITIAL = 'initial', @@ -46,7 +47,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.ts b/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.ts index e999259..f53a8ff 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.ts +++ b/chrome/browser/resources/settings/privacy_page/security_keys_set_pin_dialog.ts
@@ -25,6 +25,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SecurityKeysPINBrowserProxy, SecurityKeysPINBrowserProxyImpl} from './security_keys_browser_proxy.js'; +import {getTemplate} from './security_keys_set_pin_dialog.html.js'; export enum SetPINDialogPage { INITIAL = 'initial', @@ -58,7 +59,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/security_keys_subpage.ts b/chrome/browser/resources/settings/privacy_page/security_keys_subpage.ts index 57ce366..8769bba2 100644 --- a/chrome/browser/resources/settings/privacy_page/security_keys_subpage.ts +++ b/chrome/browser/resources/settings/privacy_page/security_keys_subpage.ts
@@ -21,6 +21,8 @@ import {routes} from '../route.js'; import {Router} from '../router.js'; +import {getTemplate} from './security_keys_subpage.html.js'; + interface SecurityKeysSubpageElement { $: { setPINButton: HTMLElement, @@ -34,7 +36,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_page/security_page.ts b/chrome/browser/resources/settings/privacy_page/security_page.ts index 47e4264..d810b361 100644 --- a/chrome/browser/resources/settings/privacy_page/security_page.ts +++ b/chrome/browser/resources/settings/privacy_page/security_page.ts
@@ -23,7 +23,6 @@ import {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js'; import {loadTimeData} from '../i18n_setup.js'; import {MetricsBrowserProxy, MetricsBrowserProxyImpl, PrivacyElementInteractions, SafeBrowsingInteractions} from '../metrics_browser_proxy.js'; - // <if expr="chromeos_ash or chromeos_lacros"> import {OpenWindowProxyImpl} from '../open_window_proxy.js'; // </if> @@ -34,6 +33,7 @@ import {SettingsCollapseRadioButtonElement} from './collapse_radio_button.js'; import {PrivacyPageBrowserProxy, PrivacyPageBrowserProxyImpl} from './privacy_page_browser_proxy.js'; +import {getTemplate} from './security_page.html.js'; /** * Enumeration of all safe browsing modes. Must be kept in sync with the enum @@ -72,7 +72,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/privacy_sandbox/BUILD.gn b/chrome/browser/resources/settings/privacy_sandbox/BUILD.gn index 045edae..6b591e7c 100644 --- a/chrome/browser/resources/settings/privacy_sandbox/BUILD.gn +++ b/chrome/browser/resources/settings/privacy_sandbox/BUILD.gn
@@ -13,6 +13,7 @@ out_grd = "$target_gen_dir/resources.grdp" input_files = [ "privacy_sandbox/app.js", + "privacy_sandbox/app.html.js", "privacy_sandbox/privacy_sandbox_browser_proxy.js", ] input_files_base_dir = rebase_path("$target_gen_dir/../tsc", root_build_dir)
diff --git a/chrome/browser/resources/settings/privacy_sandbox/app.ts b/chrome/browser/resources/settings/privacy_sandbox/app.ts index 8ea9aac..c6f7ee3 100644 --- a/chrome/browser/resources/settings/privacy_sandbox/app.ts +++ b/chrome/browser/resources/settings/privacy_sandbox/app.ts
@@ -14,6 +14,7 @@ // with |optimize_webui="true"|. import {CrSettingsPrefs, HatsBrowserProxyImpl, loadTimeData, MetricsBrowserProxy, MetricsBrowserProxyImpl, PrefsMixin, SettingsToggleButtonElement, TrustSafetyInteraction} from '../settings.js'; +import {getTemplate} from './app.html.js'; import {FlocIdentifier, PrivacySandboxBrowserProxy, PrivacySandboxBrowserProxyImpl} from './privacy_sandbox_browser_proxy.js'; const PrivacySandboxAppElementBase = PrefsMixin(PolymerElement); @@ -24,7 +25,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/relaunch_confirmation_dialog.ts b/chrome/browser/resources/settings/relaunch_confirmation_dialog.ts index 430d5b77..366c78f 100644 --- a/chrome/browser/resources/settings/relaunch_confirmation_dialog.ts +++ b/chrome/browser/resources/settings/relaunch_confirmation_dialog.ts
@@ -11,6 +11,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {LifetimeBrowserProxyImpl} from './lifetime_browser_proxy.js'; +import {getTemplate} from './relaunch_confirmation_dialog.html.js'; import {RestartType} from './relaunch_mixin.js'; export interface RelaunchConfirmationDialogElement { @@ -46,7 +47,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/reset_page/reset_page.ts b/chrome/browser/resources/settings/reset_page/reset_page.ts index 70f3377..a11a2388 100644 --- a/chrome/browser/resources/settings/reset_page/reset_page.ts +++ b/chrome/browser/resources/settings/reset_page/reset_page.ts
@@ -11,10 +11,10 @@ import '../settings_page/settings_animated_pages.js'; import '../settings_shared_css.js'; import './reset_profile_dialog.js'; - // <if expr="_google_chrome and is_win"> import '../chrome_cleanup_page/chrome_cleanup_page.js'; import '../incompatible_applications_page/incompatible_applications_page.js'; + // </if> import {CrLazyRenderElement} from 'chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.m.js'; @@ -23,7 +23,6 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {BaseMixin} from '../base_mixin.js'; - // <if expr="_google_chrome and is_win"> import {loadTimeData} from '../i18n_setup.js'; // </if> @@ -31,6 +30,7 @@ import {routes} from '../route.js'; import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../router.js'; +import {getTemplate} from './reset_page.html.js'; import {SettingsResetProfileDialogElement} from './reset_profile_dialog.js'; export interface SettingsResetPageElement { @@ -50,7 +50,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/reset_page/reset_profile_banner.ts b/chrome/browser/resources/settings/reset_page/reset_profile_banner.ts index fed0094..3691fc0 100644 --- a/chrome/browser/resources/settings/reset_page/reset_profile_banner.ts +++ b/chrome/browser/resources/settings/reset_page/reset_profile_banner.ts
@@ -17,6 +17,7 @@ import {Router} from '../router.js'; import {ResetBrowserProxyImpl} from './reset_browser_proxy.js'; +import {getTemplate} from './reset_profile_banner.html.js'; export interface SettingsResetProfileBannerElement { $: { @@ -32,7 +33,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } connectedCallback() {
diff --git a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.ts b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.ts index 347c7f9..8949d1f 100644 --- a/chrome/browser/resources/settings/reset_page/reset_profile_dialog.ts +++ b/chrome/browser/resources/settings/reset_page/reset_profile_dialog.ts
@@ -30,6 +30,7 @@ import {Router} from '../router.js'; import {ResetBrowserProxy, ResetBrowserProxyImpl} from './reset_browser_proxy.js'; +import {getTemplate} from './reset_profile_dialog.html.js'; export interface SettingsResetProfileDialogElement { $: { @@ -50,7 +51,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts index 18cd0d4..e841f93 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_child.ts
@@ -19,6 +19,7 @@ import {assertNotReached} from 'chrome://resources/js/assert.m.js'; import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './safety_check_child.html.js'; /** * UI states a safety check child can be in. Defines the basic UI of the child. @@ -39,7 +40,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_chrome_cleaner_child.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_chrome_cleaner_child.ts index 6ef36ad..c0416003 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_chrome_cleaner_child.ts +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_chrome_cleaner_child.ts
@@ -19,6 +19,7 @@ import {SafetyCheckCallbackConstants, SafetyCheckChromeCleanerStatus} from './safety_check_browser_proxy.js'; import {SafetyCheckIconStatus} from './safety_check_child.js'; +import {getTemplate} from './safety_check_chrome_cleaner_child.html.js'; type ChromeCleanerChangedEvent = { newState: SafetyCheckChromeCleanerStatus, @@ -35,7 +36,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_child.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_child.ts index ceca0d0..2487827 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_child.ts +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_extensions_child.ts
@@ -17,6 +17,7 @@ import {SafetyCheckCallbackConstants, SafetyCheckExtensionsStatus} from './safety_check_browser_proxy.js'; import {SafetyCheckIconStatus} from './safety_check_child.js'; +import {getTemplate} from './safety_check_extensions_child.html.js'; type ExtensionsChangedEvent = { newState: SafetyCheckExtensionsStatus, @@ -33,7 +34,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts index 0951ca0..3e52cd7 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_page.ts
@@ -20,9 +20,9 @@ import './safety_check_passwords_child.js'; import './safety_check_safe_browsing_child.js'; import './safety_check_updates_child.js'; - // <if expr="_google_chrome and is_win"> import './safety_check_chrome_cleaner_child.js'; + // </if> import {I18nMixin} from 'chrome://resources/js/i18n_mixin.js'; @@ -31,10 +31,11 @@ import {HatsBrowserProxyImpl, TrustSafetyInteraction} from '../hats_browser_proxy.js'; import {MetricsBrowserProxy, MetricsBrowserProxyImpl, SafetyCheckInteractions} from '../metrics_browser_proxy.js'; - import {routes} from '../route.js'; import {Router} from '../router.js'; + import {SafetyCheckBrowserProxy, SafetyCheckBrowserProxyImpl, SafetyCheckCallbackConstants, SafetyCheckParentStatus} from './safety_check_browser_proxy.js'; +import {getTemplate} from './safety_check_page.html.js'; type ParentChangedEvent = { newState: SafetyCheckParentStatus, @@ -51,7 +52,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_child.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_child.ts index 7d03ae6..a868d76 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_child.ts +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_passwords_child.ts
@@ -19,6 +19,7 @@ import {SafetyCheckCallbackConstants, SafetyCheckPasswordsStatus} from './safety_check_browser_proxy.js'; import {SafetyCheckIconStatus} from './safety_check_child.js'; +import {getTemplate} from './safety_check_passwords_child.html.js'; type PasswordsChangedEvent = { newState: SafetyCheckPasswordsStatus, @@ -35,7 +36,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_child.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_child.ts index 16d6d69..f2009f4 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_child.ts +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_safe_browsing_child.ts
@@ -18,6 +18,7 @@ import {SafetyCheckCallbackConstants, SafetyCheckSafeBrowsingStatus} from './safety_check_browser_proxy.js'; import {SafetyCheckIconStatus} from './safety_check_child.js'; +import {getTemplate} from './safety_check_safe_browsing_child.html.js'; type SafeBrowsingChangedEvent = { newState: SafetyCheckSafeBrowsingStatus, @@ -34,7 +35,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/safety_check_page/safety_check_updates_child.ts b/chrome/browser/resources/settings/safety_check_page/safety_check_updates_child.ts index f7d1ee8..52a4efa3 100644 --- a/chrome/browser/resources/settings/safety_check_page/safety_check_updates_child.ts +++ b/chrome/browser/resources/settings/safety_check_page/safety_check_updates_child.ts
@@ -10,6 +10,7 @@ // <if expr="not chromeos_ash"> import '../relaunch_confirmation_dialog.js'; + // </if> import {assertNotReached} from 'chrome://resources/js/assert.m.js'; @@ -19,8 +20,10 @@ import {MetricsBrowserProxy, MetricsBrowserProxyImpl, SafetyCheckInteractions} from '../metrics_browser_proxy.js'; import {RelaunchMixin, RestartType} from '../relaunch_mixin.js'; + import {SafetyCheckCallbackConstants, SafetyCheckUpdatesStatus} from './safety_check_browser_proxy.js'; import {SafetyCheckIconStatus} from './safety_check_child.js'; +import {getTemplate} from './safety_check_updates_child.html.js'; type UpdatesChangedEvent = { newState: SafetyCheckUpdatesStatus, @@ -37,7 +40,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.ts b/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.ts index 757b7eb9..a0c6b04 100644 --- a/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.ts +++ b/chrome/browser/resources/settings/search_engines_page/omnibox_extension_entry.ts
@@ -19,6 +19,7 @@ import {ExtensionControlBrowserProxy, ExtensionControlBrowserProxyImpl} from '../extension_control_browser_proxy.js'; +import {getTemplate} from './omnibox_extension_entry.html.js'; import {SearchEngine} from './search_engines_browser_proxy.js'; export interface SettingsOmniboxExtensionEntryElement { @@ -39,7 +40,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engine_delete_confirmation_dialog.ts b/chrome/browser/resources/settings/search_engines_page/search_engine_delete_confirmation_dialog.ts index 284d360..f96953f 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engine_delete_confirmation_dialog.ts +++ b/chrome/browser/resources/settings/search_engines_page/search_engine_delete_confirmation_dialog.ts
@@ -16,6 +16,7 @@ import {loadTimeData} from '../i18n_setup.js'; +import {getTemplate} from './search_engine_delete_confirmation_dialog.html.js'; import {SearchEngine, SearchEnginesBrowserProxy, SearchEnginesBrowserProxyImpl, SearchEnginesInfo} from './search_engines_browser_proxy.js'; export interface SettingsSearchEngineDeleteConfirmationDialogElement { @@ -36,7 +37,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engine_edit_dialog.ts b/chrome/browser/resources/settings/search_engines_page/search_engine_edit_dialog.ts index 0a21fa7..628c944 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engine_edit_dialog.ts +++ b/chrome/browser/resources/settings/search_engines_page/search_engine_edit_dialog.ts
@@ -18,6 +18,7 @@ import {loadTimeData} from '../i18n_setup.js'; +import {getTemplate} from './search_engine_edit_dialog.html.js'; import {SearchEngine, SearchEnginesBrowserProxy, SearchEnginesBrowserProxyImpl, SearchEnginesInfo} from './search_engines_browser_proxy.js'; export interface SettingsSearchEngineEditDialogElement { @@ -41,7 +42,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engine_entry.ts b/chrome/browser/resources/settings/search_engines_page/search_engine_entry.ts index e35cee7..534fc0875 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engine_entry.ts +++ b/chrome/browser/resources/settings/search_engines_page/search_engine_entry.ts
@@ -16,6 +16,7 @@ import {AnchorAlignment} from 'chrome://resources/cr_elements/cr_action_menu/cr_action_menu.js'; import {assert} from 'chrome://resources/js/assert.m.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './search_engine_entry.html.js'; import {SearchEngine, SearchEnginesBrowserProxy, SearchEnginesBrowserProxyImpl} from './search_engines_browser_proxy.js'; @@ -33,7 +34,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_list.ts b/chrome/browser/resources/settings/search_engines_page/search_engines_list.ts index d6e8094..1c235ad2 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engines_list.ts +++ b/chrome/browser/resources/settings/search_engines_page/search_engines_list.ts
@@ -14,6 +14,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SearchEngine} from './search_engines_browser_proxy.js'; +import {getTemplate} from './search_engines_list.html.js'; export class SettingsSearchEnginesListElement extends PolymerElement { static get is() { @@ -21,7 +22,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/search_engines_page/search_engines_page.ts b/chrome/browser/resources/settings/search_engines_page/search_engines_page.ts index 8f21ef4..22d2b10 100644 --- a/chrome/browser/resources/settings/search_engines_page/search_engines_page.ts +++ b/chrome/browser/resources/settings/search_engines_page/search_engines_page.ts
@@ -31,6 +31,7 @@ import {routes} from '../route.js'; import {SearchEngine, SearchEnginesBrowserProxy, SearchEnginesBrowserProxyImpl, SearchEnginesInfo, SearchEnginesInteractions} from './search_engines_browser_proxy.js'; +import {getTemplate} from './search_engines_page.html.js'; type SearchEngineEditEvent = CustomEvent<{ engine: SearchEngine, @@ -61,7 +62,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/search_page/search_page.ts b/chrome/browser/resources/settings/search_page/search_page.ts index 166c773..21816ef 100644 --- a/chrome/browser/resources/settings/search_page/search_page.ts +++ b/chrome/browser/resources/settings/search_page/search_page.ts
@@ -28,6 +28,8 @@ import {Router} from '../router.js'; import {SearchEngine, SearchEnginesBrowserProxy, SearchEnginesBrowserProxyImpl, SearchEnginesInfo} from '../search_engines_page/search_engines_browser_proxy.js'; +import {getTemplate} from './search_page.html.js'; + const SettingsSearchPageElementBase = BaseMixin(I18nMixin(PolymerElement)); export class SettingsSearchPageElement extends SettingsSearchPageElementBase { @@ -36,7 +38,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/settings.gni b/chrome/browser/resources/settings/settings.gni index 150fc18..8f16572e 100644 --- a/chrome/browser/resources/settings/settings.gni +++ b/chrome/browser/resources/settings/settings.gni
@@ -14,14 +14,8 @@ # -----------------web_component_files start ----------------------------------- +# Files holding a Polymer element definition and have an equivalent .html file. web_component_files = [ - "icons.ts", - "settings_vars_css.ts", - "settings_page_css.ts", - "settings_shared_css.ts", - "site_favicon.ts", - - # Subfolder files. "a11y_page/a11y_page.ts", "a11y_page/captions_subpage.ts", "a11y_page/live_caption_section.ts", @@ -32,9 +26,8 @@ "autofill_page/address_edit_dialog.ts", "autofill_page/address_remove_confirmation_dialog.ts", "autofill_page/autofill_page.ts", - "autofill_page/avatar_icon.ts", "autofill_page/autofill_section.ts", - "autofill_page/passwords_list_handler.ts", + "autofill_page/avatar_icon.ts", "autofill_page/credit_card_edit_dialog.ts", "autofill_page/credit_card_list_entry.ts", "autofill_page/password_check_edit_dialog.ts", @@ -42,15 +35,15 @@ "autofill_page/password_check_list_item.ts", "autofill_page/password_check.ts", "autofill_page/password_edit_dialog.ts", - "autofill_page/password_remove_dialog.ts", "autofill_page/password_list_item.ts", "autofill_page/password_move_multiple_passwords_to_account_dialog.ts", "autofill_page/password_move_to_account_dialog.ts", "autofill_page/password_remove_confirmation_dialog.ts", - "autofill_page/passwords_export_dialog.ts", - "autofill_page/passwords_section.ts", + "autofill_page/password_remove_dialog.ts", "autofill_page/passwords_device_section.ts", - "autofill_page/passwords_shared_css.ts", + "autofill_page/passwords_export_dialog.ts", + "autofill_page/passwords_list_handler.ts", + "autofill_page/passwords_section.ts", "autofill_page/payments_list.ts", "autofill_page/payments_section.ts", "autofill_page/upi_id_list_entry.ts", @@ -85,31 +78,30 @@ "privacy_page/do_not_track_toggle.ts", "privacy_page/personalization_options.ts", "privacy_page/privacy_page.ts", - "privacy_page/privacy_review_promo.ts", - "privacy_page/secure_dns.ts", - "privacy_page/secure_dns_input.ts", - "privacy_page/security_keys_bio_enroll_dialog.ts", - "privacy_page/security_keys_credential_management_dialog.ts", - "privacy_page/security_keys_pin_field.ts", - "privacy_page/security_keys_reset_dialog.ts", - "privacy_page/security_keys_set_pin_dialog.ts", - "privacy_page/security_keys_subpage.ts", - "privacy_page/security_keys_phones_subpage.ts", - "privacy_page/security_keys_phones_list.ts", - "privacy_page/security_keys_phones_dialog.ts", - "privacy_page/security_page.ts", "privacy_page/privacy_review/privacy_review_clear_on_exit_fragment.ts", "privacy_page/privacy_review/privacy_review_completion_fragment.ts", "privacy_page/privacy_review/privacy_review_completion_link_row.ts", "privacy_page/privacy_review/privacy_review_cookies_fragment.ts", "privacy_page/privacy_review/privacy_review_description_item.ts", - "privacy_page/privacy_review/privacy_review_fragment_shared_css.ts", "privacy_page/privacy_review/privacy_review_history_sync_fragment.ts", "privacy_page/privacy_review/privacy_review_msbb_fragment.ts", "privacy_page/privacy_review/privacy_review_page.ts", "privacy_page/privacy_review/privacy_review_safe_browsing_fragment.ts", "privacy_page/privacy_review/privacy_review_welcome_fragment.ts", + "privacy_page/privacy_review_promo.ts", "privacy_page/privacy_review/step_indicator.ts", + "privacy_page/secure_dns_input.ts", + "privacy_page/secure_dns.ts", + "privacy_page/security_keys_bio_enroll_dialog.ts", + "privacy_page/security_keys_credential_management_dialog.ts", + "privacy_page/security_keys_phones_dialog.ts", + "privacy_page/security_keys_phones_list.ts", + "privacy_page/security_keys_phones_subpage.ts", + "privacy_page/security_keys_pin_field.ts", + "privacy_page/security_keys_reset_dialog.ts", + "privacy_page/security_keys_set_pin_dialog.ts", + "privacy_page/security_keys_subpage.ts", + "privacy_page/security_page.ts", "privacy_sandbox/app.ts", "reset_page/reset_page.ts", "reset_page/reset_profile_banner.ts", @@ -120,45 +112,43 @@ "safety_check_page/safety_check_passwords_child.ts", "safety_check_page/safety_check_safe_browsing_child.ts", "safety_check_page/safety_check_updates_child.ts", - "search_page/search_page.ts", "search_engines_page/omnibox_extension_entry.ts", "search_engines_page/search_engine_delete_confirmation_dialog.ts", "search_engines_page/search_engine_edit_dialog.ts", - "search_engines_page/search_engine_entry_css.ts", "search_engines_page/search_engine_entry.ts", "search_engines_page/search_engines_list.ts", "search_engines_page/search_engines_page.ts", + "search_page/search_page.ts", "settings_main/settings_main.ts", "settings_menu/settings_menu.ts", "settings_page/settings_animated_pages.ts", "settings_page/settings_section.ts", "settings_page/settings_subpage.ts", "settings_ui/settings_ui.ts", + "site_favicon.ts", "site_settings/add_site_dialog.ts", "site_settings/all_sites.ts", - "site_settings/all_sites_icons.ts", "site_settings/category_default_setting.ts", "site_settings/category_setting_exceptions.ts", - "site_settings/chooser_exception_list.ts", "site_settings/chooser_exception_list_entry.ts", - "site_settings/clear_storage_dialog_css.ts", + "site_settings/chooser_exception_list.ts", "site_settings/edit_exception_dialog.ts", "site_settings/media_picker.ts", - "site_settings/pdf_documents.ts", - "site_settings/protocol_handlers.ts", - "site_settings/settings_category_default_radio_group.ts", - "site_settings/site_data.ts", - "site_settings/site_data_details_subpage.ts", - "site_settings/site_data_entry.ts", - "site_settings/site_details.ts", - "site_settings/site_details_permission.ts", - "site_settings/site_entry.ts", - "site_settings/site_list.ts", - "site_settings/site_list_entry.ts", - "site_settings/zoom_levels.ts", "site_settings_page/recent_site_permissions.ts", "site_settings_page/site_settings_list.ts", "site_settings_page/site_settings_page.ts", + "site_settings/pdf_documents.ts", + "site_settings/protocol_handlers.ts", + "site_settings/settings_category_default_radio_group.ts", + "site_settings/site_data_details_subpage.ts", + "site_settings/site_data_entry.ts", + "site_settings/site_data.ts", + "site_settings/site_details_permission.ts", + "site_settings/site_details.ts", + "site_settings/site_entry.ts", + "site_settings/site_list_entry.ts", + "site_settings/site_list.ts", + "site_settings/zoom_levels.ts", ] if (!is_chromeos_ash) { @@ -199,9 +189,21 @@ # -----------------web_component_files end ------------------------------------ +# Files that are passed as input to html_to_wrapper(). +html_files = [] +foreach(f, web_component_files) { + html_files += [ string_replace(f, ".ts", ".html") ] +} + +# Files that are generated by html_to_wrapper(). +html_wrapper_files = [] +foreach(f, html_files) { + html_wrapper_files += [ f + ".ts" ] +} + # -----------------non_web_component_files start ------------------------------ -non_webcomponent_files = [ +non_web_component_files = [ "a11y_page/captions_browser_proxy.ts", "about_page/about_page_browser_proxy.ts", "appearance_page/appearance_browser_proxy.ts", @@ -266,23 +268,23 @@ ] if (is_chromeos_ash || is_chromeos_lacros) { - non_webcomponent_files += [ "autofill_page/blocking_request_manager.ts" ] + non_web_component_files += [ "autofill_page/blocking_request_manager.ts" ] } if (is_chromeos_ash) { - non_webcomponent_files += [ + non_web_component_files += [ "people_page/account_manager_browser_proxy.ts", "site_settings/android_info_browser_proxy.ts", ] } else { if (!is_chromeos_lacros) { - non_webcomponent_files += [ + non_web_component_files += [ "default_browser_page/default_browser_browser_proxy.ts", "people_page/import_data_browser_proxy.ts", "system_page/system_page_browser_proxy.ts", ] } - non_webcomponent_files += [ + non_web_component_files += [ "languages_page/languages.ts", "languages_page/languages_browser_proxy.ts", "languages_page/languages_settings_metrics_proxy.ts", @@ -292,9 +294,26 @@ } if (is_win) { - non_webcomponent_files += [ + non_web_component_files += [ "chrome_cleanup_page/chrome_cleanup_proxy.ts", "incompatible_applications_page/incompatible_applications_browser_proxy.ts", ] } + # -----------------non_web_component_files end --------------------------------- + +ts_files = web_component_files + non_web_component_files + +css_wrapper_files = [ + "icons.ts", + "settings_page_css.ts", + "settings_shared_css.ts", + "settings_vars_css.ts", + + # subfolder files + "autofill_page/passwords_shared_css.ts", + "privacy_page/privacy_review/privacy_review_fragment_shared_css.ts", + "search_engines_page/search_engine_entry_css.ts", + "site_settings/all_sites_icons.ts", + "site_settings/clear_storage_dialog_css.ts", +]
diff --git a/chrome/browser/resources/settings/settings_main/settings_main.ts b/chrome/browser/resources/settings/settings_main/settings_main.ts index fbfb8aa..9622e7f 100644 --- a/chrome/browser/resources/settings/settings_main/settings_main.ts +++ b/chrome/browser/resources/settings/settings_main/settings_main.ts
@@ -28,6 +28,8 @@ import {routes} from '../route.js'; import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../router.js'; +import {getTemplate} from './settings_main.html.js'; + type MainPageVisibility = { about: boolean, settings: boolean, @@ -48,7 +50,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/settings_menu/settings_menu.ts b/chrome/browser/resources/settings/settings_menu/settings_menu.ts index 3af5385..6e4bc4d 100644 --- a/chrome/browser/resources/settings/settings_menu/settings_menu.ts +++ b/chrome/browser/resources/settings/settings_menu/settings_menu.ts
@@ -26,6 +26,8 @@ import {PageVisibility} from '../page_visibility.js'; import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../router.js'; +import {getTemplate} from './settings_menu.html.js'; + export interface SettingsMenuElement { $: { autofill: HTMLLinkElement, @@ -46,7 +48,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/settings_page/settings_animated_pages.ts b/chrome/browser/resources/settings/settings_page/settings_animated_pages.ts index 7bc0f985..34fc165 100644 --- a/chrome/browser/resources/settings/settings_page/settings_animated_pages.ts +++ b/chrome/browser/resources/settings/settings_page/settings_animated_pages.ts
@@ -18,7 +18,6 @@ import {assert} from '//resources/js/assert.m.js'; import {focusWithoutInk} from '//resources/js/cr/ui/focus_without_ink.m.js'; - // <if expr="chromeos"> import {loadTimeData} from '//resources/js/load_time_data.m.js'; // </if> @@ -27,11 +26,12 @@ import {DomIf, FlattenedNodesObserver, html, microTask, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../router.js'; - // <if expr="chromeos"> import {getSettingIdParameter} from '../setting_id_param_util.js'; // </if> +import {getTemplate} from './settings_animated_pages.html.js'; + import {SettingsSubpageElement} from './settings_subpage.js'; type FocusConfig = Map<string, (string|Element|(() => void))>; @@ -51,7 +51,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/settings_page/settings_section.ts b/chrome/browser/resources/settings/settings_page/settings_section.ts index 61dddb9e..88e92a50 100644 --- a/chrome/browser/resources/settings/settings_page/settings_section.ts +++ b/chrome/browser/resources/settings/settings_page/settings_section.ts
@@ -19,6 +19,7 @@ import '//resources/cr_elements/shared_vars_css.m.js'; import {html, PolymerElement} from '//resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './settings_section.html.js'; export class SettingsSectionElement extends PolymerElement { static get is() { @@ -26,7 +27,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/settings_page/settings_subpage.ts b/chrome/browser/resources/settings/settings_page/settings_subpage.ts index 51d6e51..5d049adf0 100644 --- a/chrome/browser/resources/settings/settings_page/settings_subpage.ts +++ b/chrome/browser/resources/settings/settings_page/settings_subpage.ts
@@ -29,6 +29,8 @@ import {Route, RouteObserverMixin, Router} from '../router.js'; import {getSettingIdParameter} from '../setting_id_param_util.js'; +import {getTemplate} from './settings_subpage.html.js'; + export interface SettingsSubpageElement { $: { closeButton: HTMLElement, @@ -286,7 +288,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } }
diff --git a/chrome/browser/resources/settings/settings_ui/settings_ui.ts b/chrome/browser/resources/settings/settings_ui/settings_ui.ts index bfca7b4..e478169b 100644 --- a/chrome/browser/resources/settings/settings_ui/settings_ui.ts +++ b/chrome/browser/resources/settings/settings_ui/settings_ui.ts
@@ -39,6 +39,8 @@ import {SettingsMainElement} from '../settings_main/settings_main.js'; import {SettingsMenuElement} from '../settings_menu/settings_menu.js'; +import {getTemplate} from './settings_ui.html.js'; + declare global { interface HTMLElementEventMap { 'refresh-pref': CustomEvent<string>; @@ -73,7 +75,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_favicon.ts b/chrome/browser/resources/settings/site_favicon.ts index 226e0ef..90d186d7 100644 --- a/chrome/browser/resources/settings/site_favicon.ts +++ b/chrome/browser/resources/settings/site_favicon.ts
@@ -9,6 +9,7 @@ import {getFavicon, getFaviconForPageURL} from 'chrome://resources/js/icon.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './site_favicon.html.js'; export interface SiteFaviconElement { $: { @@ -22,7 +23,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/add_site_dialog.ts b/chrome/browser/resources/settings/site_settings/add_site_dialog.ts index b5758e6..5db40bc 100644 --- a/chrome/browser/resources/settings/site_settings/add_site_dialog.ts +++ b/chrome/browser/resources/settings/site_settings/add_site_dialog.ts
@@ -22,6 +22,7 @@ import {loadTimeData} from '../i18n_setup.js'; +import {getTemplate} from './add_site_dialog.html.js'; import {ContentSetting, ContentSettingsTypes, SITE_EXCEPTION_WILDCARD} from './constants.js'; import {SiteSettingsMixin, SiteSettingsMixinInterface} from './site_settings_mixin.js'; @@ -44,7 +45,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/all_sites.ts b/chrome/browser/resources/settings/site_settings/all_sites.ts index fb06f49..d987cfe 100644 --- a/chrome/browser/resources/settings/site_settings/all_sites.ts +++ b/chrome/browser/resources/settings/site_settings/all_sites.ts
@@ -34,6 +34,7 @@ import {routes} from '../route.js'; import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../router.js'; +import {getTemplate} from './all_sites.html.js'; import {ALL_SITES_DIALOG, AllSitesAction2, ContentSetting, SortMethod} from './constants.js'; import {LocalDataBrowserProxy, LocalDataBrowserProxyImpl} from './local_data_browser_proxy.js'; import {SiteSettingsMixin, SiteSettingsMixinInterface} from './site_settings_mixin.js'; @@ -99,7 +100,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/category_default_setting.ts b/chrome/browser/resources/settings/site_settings/category_default_setting.ts index 4460039..2d0066f 100644 --- a/chrome/browser/resources/settings/site_settings/category_default_setting.ts +++ b/chrome/browser/resources/settings/site_settings/category_default_setting.ts
@@ -43,6 +43,7 @@ import {loadTimeData} from '../i18n_setup.js'; +import {getTemplate} from './category_default_setting.html.js'; import {ContentSetting, ContentSettingsTypes} from './constants.js'; import {SiteSettingsMixin} from './site_settings_mixin.js'; import {ContentSettingProvider, DefaultContentSetting} from './site_settings_prefs_browser_proxy.js'; @@ -64,7 +65,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/category_setting_exceptions.ts b/chrome/browser/resources/settings/site_settings/category_setting_exceptions.ts index 6a2f06a..fba97bf 100644 --- a/chrome/browser/resources/settings/site_settings/category_setting_exceptions.ts +++ b/chrome/browser/resources/settings/site_settings/category_setting_exceptions.ts
@@ -13,6 +13,8 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {loadTimeData} from '../i18n_setup.js'; + +import {getTemplate} from './category_setting_exceptions.html.js'; import {ContentSetting, ContentSettingsTypes} from './constants.js'; import {SiteSettingsMixin} from './site_settings_mixin.js'; import {ContentSettingProvider} from './site_settings_prefs_browser_proxy.js'; @@ -27,7 +29,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/chooser_exception_list.ts b/chrome/browser/resources/settings/site_settings/chooser_exception_list.ts index a8e9b92..9cf54f6 100644 --- a/chrome/browser/resources/settings/site_settings/chooser_exception_list.ts +++ b/chrome/browser/resources/settings/site_settings/chooser_exception_list.ts
@@ -19,6 +19,7 @@ import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; import {PaperTooltipElement} from 'chrome://resources/polymer/v3_0/paper-tooltip/paper-tooltip.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './chooser_exception_list.html.js'; import {ChooserType, ContentSettingsTypes} from './constants.js'; import {SiteSettingsMixin} from './site_settings_mixin.js'; @@ -40,7 +41,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/chooser_exception_list_entry.ts b/chrome/browser/resources/settings/site_settings/chooser_exception_list_entry.ts index 4f108045..c8d86aa 100644 --- a/chrome/browser/resources/settings/site_settings/chooser_exception_list_entry.ts +++ b/chrome/browser/resources/settings/site_settings/chooser_exception_list_entry.ts
@@ -15,6 +15,7 @@ import './site_list_entry.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './chooser_exception_list_entry.html.js'; import {ChooserException} from './site_settings_prefs_browser_proxy.js'; @@ -30,7 +31,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/edit_exception_dialog.ts b/chrome/browser/resources/settings/site_settings/edit_exception_dialog.ts index fec19a1..603d8cd 100644 --- a/chrome/browser/resources/settings/site_settings/edit_exception_dialog.ts +++ b/chrome/browser/resources/settings/site_settings/edit_exception_dialog.ts
@@ -15,6 +15,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {SITE_EXCEPTION_WILDCARD} from './constants.js'; +import {getTemplate} from './edit_exception_dialog.html.js'; import {SiteException, SiteSettingsPrefsBrowserProxy, SiteSettingsPrefsBrowserProxyImpl} from './site_settings_prefs_browser_proxy.js'; export interface SettingsEditExceptionDialogElement { @@ -30,7 +31,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/media_picker.ts b/chrome/browser/resources/settings/site_settings/media_picker.ts index c1ed093..4486c6dd 100644 --- a/chrome/browser/resources/settings/site_settings/media_picker.ts +++ b/chrome/browser/resources/settings/site_settings/media_picker.ts
@@ -13,6 +13,7 @@ import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; import {html, microTask, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './media_picker.html.js'; import {SiteSettingsMixin} from './site_settings_mixin.js'; import {MediaPickerEntry} from './site_settings_prefs_browser_proxy.js'; @@ -33,7 +34,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/pdf_documents.ts b/chrome/browser/resources/settings/site_settings/pdf_documents.ts index d56fb80..f3c74aa2 100644 --- a/chrome/browser/resources/settings/site_settings/pdf_documents.ts +++ b/chrome/browser/resources/settings/site_settings/pdf_documents.ts
@@ -12,6 +12,7 @@ import '../settings_shared_css.js'; import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './pdf_documents.html.js'; class SettingsPdfDocumentsElement extends PolymerElement { static get is() { @@ -19,7 +20,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/protocol_handlers.ts b/chrome/browser/resources/settings/site_settings/protocol_handlers.ts index a328a53f..555bd50 100644 --- a/chrome/browser/resources/settings/site_settings/protocol_handlers.ts +++ b/chrome/browser/resources/settings/site_settings/protocol_handlers.ts
@@ -24,6 +24,7 @@ import {WebUIListenerMixin} from 'chrome://resources/js/web_ui_listener_mixin.js'; import {DomRepeatEvent, html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +import {getTemplate} from './protocol_handlers.html.js'; import {SiteSettingsMixin} from './site_settings_mixin.js'; @@ -78,7 +79,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.ts b/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.ts index dbd8be7d..c24b4b7 100644 --- a/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.ts +++ b/chrome/browser/resources/settings/site_settings/settings_category_default_radio_group.ts
@@ -19,6 +19,7 @@ import {SettingsCollapseRadioButtonElement} from '../privacy_page/collapse_radio_button.js'; import {ContentSetting, ContentSettingsTypes} from './constants.js'; +import {getTemplate} from './settings_category_default_radio_group.html.js'; import {SiteSettingsMixin} from './site_settings_mixin.js'; import {ContentSettingProvider, DefaultContentSetting} from './site_settings_prefs_browser_proxy.js'; @@ -47,7 +48,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/site_data.ts b/chrome/browser/resources/settings/site_settings/site_data.ts index e257715..ebfb3d1d 100644 --- a/chrome/browser/resources/settings/site_settings/site_data.ts +++ b/chrome/browser/resources/settings/site_settings/site_data.ts
@@ -33,6 +33,7 @@ import {Route, Router} from '../router.js'; import {LocalDataBrowserProxy, LocalDataBrowserProxyImpl, LocalDataItem} from './local_data_browser_proxy.js'; +import {getTemplate} from './site_data.html.js'; type FocusConfig = Map<string, string|(() => void)>; @@ -59,7 +60,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/site_data_details_subpage.ts b/chrome/browser/resources/settings/site_settings/site_data_details_subpage.ts index b192ba5..907dde77 100644 --- a/chrome/browser/resources/settings/site_settings/site_data_details_subpage.ts +++ b/chrome/browser/resources/settings/site_settings/site_data_details_subpage.ts
@@ -19,6 +19,7 @@ import {CookieDataForDisplay, CookieDetails, getCookieData} from './cookie_info.js'; import {LocalDataBrowserProxy, LocalDataBrowserProxyImpl} from './local_data_browser_proxy.js'; +import {getTemplate} from './site_data_details_subpage.html.js'; const categoryLabels: {[key: string]: string} = { @@ -49,7 +50,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/site_data_entry.ts b/chrome/browser/resources/settings/site_settings/site_data_entry.ts index 75e975c6..2566c66 100644 --- a/chrome/browser/resources/settings/site_settings/site_data_entry.ts +++ b/chrome/browser/resources/settings/site_settings/site_data_entry.ts
@@ -22,6 +22,7 @@ import {MetricsBrowserProxyImpl, PrivacyElementInteractions} from '../metrics_browser_proxy.js'; import {LocalDataBrowserProxyImpl, LocalDataItem} from './local_data_browser_proxy.js'; +import {getTemplate} from './site_data_entry.html.js'; const SiteDataEntryElementBase = mixinBehaviors([FocusRowBehavior], I18nMixin(PolymerElement)) as @@ -33,7 +34,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/site_details.ts b/chrome/browser/resources/settings/site_settings/site_details.ts index afd2ace..9f49d8b 100644 --- a/chrome/browser/resources/settings/site_settings/site_details.ts +++ b/chrome/browser/resources/settings/site_settings/site_details.ts
@@ -36,6 +36,7 @@ import {Route, RouteObserverMixin, RouteObserverMixinInterface, Router} from '../router.js'; import {ContentSetting, ContentSettingsTypes} from './constants.js'; +import {getTemplate} from './site_details.html.js'; import {SiteDetailsPermissionElement} from './site_details_permission.js'; import {SiteSettingsMixin, SiteSettingsMixinInterface} from './site_settings_mixin.js'; import {WebsiteUsageBrowserProxy, WebsiteUsageBrowserProxyImpl} from './website_usage_browser_proxy.js'; @@ -64,7 +65,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/site_details_permission.ts b/chrome/browser/resources/settings/site_settings/site_details_permission.ts index 80322650..3e1fb4a 100644 --- a/chrome/browser/resources/settings/site_settings/site_details_permission.ts +++ b/chrome/browser/resources/settings/site_settings/site_details_permission.ts
@@ -19,6 +19,7 @@ import {html, PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; import {ContentSetting, ContentSettingsTypes, SiteSettingSource} from './constants.js'; +import {getTemplate} from './site_details_permission.html.js'; import {SiteSettingsMixin} from './site_settings_mixin.js'; import {RawSiteException} from './site_settings_prefs_browser_proxy.js'; @@ -41,7 +42,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/site_entry.ts b/chrome/browser/resources/settings/site_settings/site_entry.ts index 4485a2d2..bcb93c2 100644 --- a/chrome/browser/resources/settings/site_settings/site_entry.ts +++ b/chrome/browser/resources/settings/site_settings/site_entry.ts
@@ -30,6 +30,7 @@ import {AllSitesAction2, SortMethod} from './constants.js'; import {LocalDataBrowserProxy, LocalDataBrowserProxyImpl} from './local_data_browser_proxy.js'; +import {getTemplate} from './site_entry.html.js'; import {SiteSettingsMixin, SiteSettingsMixinInterface} from './site_settings_mixin.js'; import {OriginInfo, SiteGroup} from './site_settings_prefs_browser_proxy.js'; @@ -62,7 +63,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/site_list.ts b/chrome/browser/resources/settings/site_settings/site_list.ts index 802b9dea..16ccdabb 100644 --- a/chrome/browser/resources/settings/site_settings/site_list.ts +++ b/chrome/browser/resources/settings/site_settings/site_list.ts
@@ -29,9 +29,11 @@ // <if expr="chromeos"> import {loadTimeData} from '../i18n_setup.js'; + import {AndroidInfoBrowserProxyImpl, AndroidSmsInfo} from './android_info_browser_proxy.js'; // </if> import {ContentSetting, ContentSettingsTypes, INVALID_CATEGORY_SUBTYPE} from './constants.js'; +import {getTemplate} from './site_list.html.js'; import {SiteSettingsMixin} from './site_settings_mixin.js'; import {RawSiteException, SiteException, SiteSettingsPrefsBrowserProxy, SiteSettingsPrefsBrowserProxyImpl} from './site_settings_prefs_browser_proxy.js'; @@ -53,7 +55,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/site_list_entry.ts b/chrome/browser/resources/settings/site_settings/site_list_entry.ts index e9ca090e0..2db353c 100644 --- a/chrome/browser/resources/settings/site_settings/site_list_entry.ts +++ b/chrome/browser/resources/settings/site_settings/site_list_entry.ts
@@ -25,6 +25,7 @@ import {Router} from '../router.js'; import {ChooserType, ContentSettingsTypes, SITE_EXCEPTION_WILDCARD} from './constants.js'; +import {getTemplate} from './site_list_entry.html.js'; import {SiteSettingsMixin, SiteSettingsMixinInterface} from './site_settings_mixin.js'; import {SiteException} from './site_settings_prefs_browser_proxy.js'; @@ -46,7 +47,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings/zoom_levels.ts b/chrome/browser/resources/settings/site_settings/zoom_levels.ts index f386d08..469b5f2 100644 --- a/chrome/browser/resources/settings/site_settings/zoom_levels.ts +++ b/chrome/browser/resources/settings/site_settings/zoom_levels.ts
@@ -22,6 +22,7 @@ import {SiteSettingsMixin} from './site_settings_mixin.js'; import {ZoomLevelEntry} from './site_settings_prefs_browser_proxy.js'; +import {getTemplate} from './zoom_levels.html.js'; export interface ZoomLevelsElement { $: { @@ -40,7 +41,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts b/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts index be928a6..fe1c17c 100644 --- a/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts +++ b/chrome/browser/resources/settings/site_settings_page/recent_site_permissions.ts
@@ -22,6 +22,8 @@ import {SiteSettingsMixin, SiteSettingsMixinInterface} from '../site_settings/site_settings_mixin.js'; import {RawSiteException, RecentSitePermissions} from '../site_settings/site_settings_prefs_browser_proxy.js'; +import {getTemplate} from './recent_site_permissions.html.js'; + type FocusConfig = Map<string, (string|(() => void))>; export interface SettingsRecentSitePermissionsElement { @@ -45,7 +47,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts b/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts index b1971c3..baaf6ab3 100644 --- a/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_list.ts
@@ -20,6 +20,8 @@ import {ContentSetting, ContentSettingsTypes, NotificationSetting} from '../site_settings/constants.js'; import {SiteSettingsPrefsBrowserProxy, SiteSettingsPrefsBrowserProxyImpl} from '../site_settings/site_settings_prefs_browser_proxy.js'; +import {getTemplate} from './site_settings_list.html.js'; + export type CategoryListItem = { route: Route, id: ContentSettingsTypes, @@ -57,7 +59,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts b/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts index 5bbe6ec..86f6076 100644 --- a/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts +++ b/chrome/browser/resources/settings/site_settings_page/site_settings_page.ts
@@ -25,6 +25,7 @@ import {ContentSettingsTypes} from '../site_settings/constants.js'; import {CategoryListItem} from './site_settings_list.js'; +import {getTemplate} from './site_settings_page.html.js'; const Id = ContentSettingsTypes; @@ -328,7 +329,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/resources/settings/system_page/system_page.ts b/chrome/browser/resources/settings/system_page/system_page.ts index 4e5c6aa..7b2947a 100644 --- a/chrome/browser/resources/settings/system_page/system_page.ts +++ b/chrome/browser/resources/settings/system_page/system_page.ts
@@ -24,6 +24,7 @@ import {SettingsToggleButtonElement} from '../controls/settings_toggle_button.js'; import {RelaunchMixin, RestartType} from '../relaunch_mixin.js'; +import {getTemplate} from './system_page.html.js'; import {SystemPageBrowserProxyImpl} from './system_page_browser_proxy.js'; @@ -42,7 +43,7 @@ } static get template() { - return html`{__html_template__}`; + return getTemplate(); } static get properties() {
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.cc b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.cc index fb3c90c..7b48c05 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.cc +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.cc
@@ -46,7 +46,7 @@ const std::string& expected_trigger, const std::string& expected_reason, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username) { event_key_ = SafeBrowsingPrivateEventRouter::kKeyUnscannedFileEvent; @@ -75,7 +75,7 @@ const std::string& expected_trigger, const std::string& expected_reason, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username) { DCHECK_EQ(expected_filenames.size(), expected_sha256s.size()); @@ -107,7 +107,7 @@ const std::string& expected_threat_type, const std::string& expected_trigger, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username, const absl::optional<std::string>& expected_scan_id) { @@ -140,7 +140,7 @@ const enterprise_connectors::ContentAnalysisResponse::Result& expected_dlp_verdict, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username, const std::string& expected_scan_id) { @@ -172,7 +172,7 @@ const std::vector<enterprise_connectors::ContentAnalysisResponse::Result>& expected_dlp_verdicts, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::vector<std::string>& expected_results, const std::string& expected_username, const std::vector<std::string>& expected_scan_ids) { @@ -209,7 +209,7 @@ const enterprise_connectors::ContentAnalysisResponse::Result& expected_dlp_verdict, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username, const std::string& expected_scan_id) { @@ -252,7 +252,7 @@ const enterprise_connectors::ContentAnalysisResponse::Result& expected_dlp_verdict, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username, const std::string& expected_scan_id) { @@ -293,7 +293,7 @@ const std::string& expected_threat_type, const std::string& expected_trigger, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username, const absl::optional<std::string>& expected_scan_id) { @@ -381,8 +381,12 @@ ValidateField(event, SafeBrowsingPrivateEventRouter::kKeyUrl, url_); ValidateFilenameMappedAttributes(event); ValidateField(event, SafeBrowsingPrivateEventRouter::kKeyTrigger, trigger_); - ValidateField(event, SafeBrowsingPrivateEventRouter::kKeyContentSize, - content_size_); + // `content_size_` needs a conversion since int64 are strings in base::Value. + absl::optional<std::string> size = + content_size_.has_value() + ? absl::optional<std::string>(base::NumberToString(*content_size_)) + : absl::nullopt; + ValidateField(event, SafeBrowsingPrivateEventRouter::kKeyContentSize, size); ValidateField(event, SafeBrowsingPrivateEventRouter::kKeyThreatType, threat_type_); ValidateField(event, SafeBrowsingPrivateEventRouter::kKeyUnscannedReason,
diff --git a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.h b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.h index 9d653ce..f7e3c11 100644 --- a/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.h +++ b/chrome/browser/safe_browsing/cloud_content_scanning/deep_scanning_test_utils.h
@@ -44,7 +44,7 @@ const std::string& expected_threat_type, const std::string& expected_trigger, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username, const absl::optional<std::string>& expected_scan_id); @@ -57,7 +57,7 @@ const enterprise_connectors::ContentAnalysisResponse::Result& expected_dlp_verdict, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username, const std::string& expected_scan_id); @@ -70,7 +70,7 @@ const std::vector<enterprise_connectors::ContentAnalysisResponse::Result>& expected_dlp_verdicts, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::vector<std::string>& expected_results, const std::string& expected_username, const std::vector<std::string>& expected_scan_ids); @@ -84,7 +84,7 @@ const enterprise_connectors::ContentAnalysisResponse::Result& expected_dlp_verdict, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username, const std::string& expected_scan_id); @@ -98,7 +98,7 @@ const enterprise_connectors::ContentAnalysisResponse::Result& expected_dlp_verdict, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username, const std::string& expected_scan_id); @@ -109,7 +109,7 @@ const std::string& expected_trigger, const std::string& expected_reason, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username); @@ -120,7 +120,7 @@ const std::string& expected_trigger, const std::string& expected_reason, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username); @@ -131,7 +131,7 @@ const std::string& expected_threat_type, const std::string& expected_trigger, const std::set<std::string>* expected_mimetypes, - int expected_content_size, + int64_t expected_content_size, const std::string& expected_result, const std::string& expected_username, const absl::optional<std::string>& expected_scan_id); @@ -185,7 +185,7 @@ absl::optional<std::string> trigger_ = absl::nullopt; absl::optional<std::string> threat_type_ = absl::nullopt; absl::optional<std::string> unscanned_reason_ = absl::nullopt; - absl::optional<int> content_size_ = absl::nullopt; + absl::optional<int64_t> content_size_ = absl::nullopt; raw_ptr<const std::set<std::string>> mimetypes_ = nullptr; std::string username_; absl::optional<bool> is_federated_ = absl::nullopt;
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinator.java index 7cc52d11..cd79dd98 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinator.java
@@ -7,7 +7,6 @@ import androidx.annotation.IntDef; import androidx.annotation.VisibleForTesting; -import org.chromium.base.Callback; import org.chromium.base.task.PostTask; import org.chromium.blink.mojom.TextFragmentReceiver; import org.chromium.chrome.browser.flags.ChromeFeatureList; @@ -15,7 +14,6 @@ import org.chromium.chrome.browser.share.share_sheet.ChromeOptionShareCallback; import org.chromium.chrome.browser.share.share_sheet.ShareSheetLinkToggleCoordinator.LinkToggleState; import org.chromium.chrome.browser.tab.EmptyTabObserver; -import org.chromium.chrome.browser.tab.SadTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.chrome.browser.tab.TabHidingType; import org.chromium.components.browser_ui.share.ShareParams; @@ -142,6 +140,7 @@ return sb.toString(); } + // TODO(http://crbug/1294855): Move canonical url request after renderer calls. private void startRequestSelector() { if (!LinkToTextBridge.shouldOfferLinkToText(new GURL(mShareUrl))) { completeRequestWithFailure(LinkGenerationError.BLOCK_LIST); @@ -157,7 +156,7 @@ } PostTask.postDelayedTask(UiThreadTaskTraits.DEFAULT, () -> timeout(), getTimeout()); - requestSelectorForCanonicalUrl(); + LinkToTextHelper.requestCanonicalUrl(mTab, this::onRequestSelectorForCanonicalUrl); } @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) @@ -180,6 +179,22 @@ @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) void onReshareSelectorsRemoteRequestCompleted(String selectors) { if (mRemoteRequestStatus == RemoteRequestStatus.CANCELLED) return; + if (selectors.isEmpty()) { + completeReshareWithFailure(LinkToTextReshareStatus.EMPTY_SELECTOR); + return; + } + + LinkToTextHelper.requestCanonicalUrl(mTab, (canonicalUrl) -> { + if (!canonicalUrl.isEmpty()) { + mShareUrl = canonicalUrl; + } + reshareRequestCompleted(selectors); + }); + } + + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + void reshareRequestCompleted(String selectors) { + if (mRemoteRequestStatus == RemoteRequestStatus.CANCELLED) return; mRemoteRequestStatus = RemoteRequestStatus.COMPLETED; completeRemoteRequestWithSuccess(selectors); @@ -254,30 +269,11 @@ LinkToTextHelper.requestSelector(mProducer, this::onRemoteRequestCompleted); } - private void requestSelectorForCanonicalUrl() { - if (shouldRequestCanonicalUrl()) { - mTab.getWebContents().getMainFrame().getCanonicalUrlForSharing(new Callback<GURL>() { - @Override - public void onResult(GURL result) { - if (!result.isEmpty()) { - mShareUrl = result.getSpec(); - } - requestSelector(); - } - }); - } else { - requestSelector(); + private void onRequestSelectorForCanonicalUrl(String canonicalUrl) { + if (!canonicalUrl.isEmpty()) { + mShareUrl = canonicalUrl; } - } - - private boolean shouldRequestCanonicalUrl() { - if (mTab.getWebContents() == null) return false; - if (mTab.getWebContents().getMainFrame() == null) return false; - if (mTab.getUrl().isEmpty()) return false; - if (mTab.isShowingErrorPage() || SadTab.isShowing(mTab)) { - return false; - } - return true; + requestSelector(); } private void setTextFragmentReceiver() {
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextHelper.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextHelper.java index 9faec6b..af1fe9e 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextHelper.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextHelper.java
@@ -9,6 +9,7 @@ import org.chromium.base.Callback; import org.chromium.blink.mojom.TextFragmentReceiver; import org.chromium.chrome.browser.flags.ChromeFeatureList; +import org.chromium.chrome.browser.tab.SadTab; import org.chromium.chrome.browser.tab.Tab; import org.chromium.content_public.browser.RenderFrameHost; import org.chromium.content_public.browser.WebContents; @@ -66,6 +67,36 @@ } /** + * Fetch the canonical url for sharing + * + * @param tab The tab to fetch the canonical url from. + * @param callback The {@link Callback} to return the tab's canonical url or an empty string + */ + public static void requestCanonicalUrl(Tab tab, Callback<String> callback) { + if (!shouldRequestCanonicalUrl(tab)) { + callback.onResult(""); + return; + } + + tab.getWebContents().getMainFrame().getCanonicalUrlForSharing(new Callback<GURL>() { + @Override + public void onResult(GURL result) { + callback.onResult(result.getSpec()); + } + }); + } + + private static boolean shouldRequestCanonicalUrl(Tab tab) { + if (tab.getWebContents() == null) return false; + if (tab.getWebContents().getMainFrame() == null) return false; + if (tab.getUrl().isEmpty()) return false; + if (tab.isShowingErrorPage() || SadTab.isShowing(tab)) { + return false; + } + return true; + } + + /** * This checks if there is a highlight in the page by iterating over the frames in the page to * find an existing selectors. *
diff --git a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediator.java b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediator.java index 7d0aa0e..8d74201 100644 --- a/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediator.java +++ b/chrome/browser/share/android/java/src/org/chromium/chrome/browser/share/screenshot/ScreenshotShareSheetMediator.java
@@ -9,7 +9,6 @@ import android.net.Uri; import org.chromium.base.Callback; -import org.chromium.base.metrics.RecordHistogram; import org.chromium.chrome.R; import org.chromium.chrome.browser.share.ChromeShareExtras; import org.chromium.chrome.browser.share.screenshot.ScreenshotShareSheetViewProperties.NoArgOperation; @@ -110,11 +109,7 @@ String isoDate = new SimpleDateFormat(sIsoDateFormat, Locale.getDefault()) .format(new Date(System.currentTimeMillis())); String title = mContext.getString(R.string.screenshot_title_for_share, isoDate); - long startTime = System.currentTimeMillis(); Callback<Uri> callback = (bitmapUri) -> { - RecordHistogram.recordMediumTimesHistogram( - "Sharing.SharingHubAndroid.TimeToSaveScreenshotImageBeforeShare", - System.currentTimeMillis() - startTime); ShareParams params = new ShareParams.Builder(window, title, /*url=*/"") .setFileUris(new ArrayList<>(Collections.singletonList(bitmapUri)))
diff --git a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java index 7dacda6..0275cb36 100644 --- a/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java +++ b/chrome/browser/share/android/javatests/src/org/chromium/chrome/browser/share/link_to_text/LinkToTextCoordinatorTest.java
@@ -151,7 +151,7 @@ void reshareHighlightedText() { mLinkToTextCoordinator.mRemoteRequestStatus = RemoteRequestStatus.REQUESTED; if (mIsRemoteRequestResultSet) { - mLinkToTextCoordinator.onReshareSelectorsRemoteRequestCompleted(mSelector); + mLinkToTextCoordinator.reshareRequestCompleted(mSelector); } } });
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc index fead1b1..187bf63 100644 --- a/chrome/browser/shell_integration_linux.cc +++ b/chrome/browser/shell_integration_linux.cc
@@ -20,7 +20,6 @@ #include "base/base_paths.h" #include "base/command_line.h" #include "base/environment.h" -#include "base/feature_list.h" #include "base/files/file_enumerator.h" #include "base/files/file_path.h" #include "base/files/file_util.h" @@ -49,7 +48,6 @@ #include "chrome/common/buildflags.h" #include "chrome/common/channel_info.h" #include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_features.h" #include "chrome/common/chrome_switches.h" #include "chrome/grit/chrome_unscaled_resources.h" #include "components/version_info/version_info.h" @@ -644,11 +642,8 @@ g_key_file_set_string(key_file, kDesktopEntry, "StartupWMClass", wmclass.c_str()); - if (base::FeatureList::IsEnabled( - features::kDesktopPWAsAppIconShortcutsMenuUI)) { - SetActionsForDesktopApplication(command_line, key_file, - std::move(action_info)); - } + SetActionsForDesktopApplication(command_line, key_file, + std::move(action_info)); gsize length = 0; gchar* data_dump = g_key_file_to_data(key_file, &length, NULL);
diff --git a/chrome/browser/shell_integration_linux_unittest.cc b/chrome/browser/shell_integration_linux_unittest.cc index 4afc3391..f4dc3b7 100644 --- a/chrome/browser/shell_integration_linux_unittest.cc +++ b/chrome/browser/shell_integration_linux_unittest.cc
@@ -21,20 +21,18 @@ #include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" -#include "base/test/scoped_feature_list.h" #include "base/test/scoped_path_override.h" #include "build/branding_buildflags.h" #include "chrome/browser/web_applications/web_app_helpers.h" #include "chrome/browser/web_applications/web_app_id.h" #include "chrome/browser/web_applications/web_app_shortcut.h" #include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_features.h" #include "components/services/app_service/public/cpp/file_handler.h" #include "content/public/test/browser_task_environment.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "url/gurl.h" #include "ui/ozone/public/ozone_platform.h" +#include "url/gurl.h" using ::testing::ElementsAre; @@ -470,9 +468,6 @@ } TEST(ShellIntegrationTest, GetDesktopFileContentsForApps) { - base::test::ScopedFeatureList feature_list; - feature_list.InitAndEnableFeature( - features::kDesktopPWAsAppIconShortcutsMenuUI); const base::FilePath kChromeExePath("/opt/google/chrome/google-chrome"); const struct { const char* const url;
diff --git a/chrome/browser/sync/test/integration/apps_helper.cc b/chrome/browser/sync/test/integration/apps_helper.cc index cfc5655..292cbd0 100644 --- a/chrome/browser/sync/test/integration/apps_helper.cc +++ b/chrome/browser/sync/test/integration/apps_helper.cc
@@ -252,7 +252,8 @@ } // namespace apps_helper -AppsMatchChecker::AppsMatchChecker() : profiles_(test()->GetAllProfiles()) { +AppsStatusChangeChecker::AppsStatusChangeChecker() + : profiles_(test()->GetAllProfiles()) { DCHECK_GE(profiles_.size(), 2U); for (Profile* profile : profiles_) { @@ -278,7 +279,7 @@ } } -AppsMatchChecker::~AppsMatchChecker() { +AppsStatusChangeChecker::~AppsStatusChangeChecker() { for (Profile* profile : profiles_) { extensions::ExtensionRegistry* registry = extensions::ExtensionRegistry::Get(profile); @@ -289,6 +290,70 @@ } } +void AppsStatusChangeChecker::OnExtensionLoaded( + content::BrowserContext* context, + const extensions::Extension* extension) { + CheckExitCondition(); +} + +void AppsStatusChangeChecker::OnExtensionUnloaded( + content::BrowserContext* context, + const extensions::Extension* extension, + extensions::UnloadedExtensionReason reason) { + CheckExitCondition(); +} + +void AppsStatusChangeChecker::OnExtensionInstalled( + content::BrowserContext* browser_context, + const extensions::Extension* extension, + bool is_update) { + CheckExitCondition(); +} + +void AppsStatusChangeChecker::OnExtensionUninstalled( + content::BrowserContext* browser_context, + const extensions::Extension* extension, + extensions::UninstallReason reason) { + CheckExitCondition(); +} + +void AppsStatusChangeChecker::OnExtensionDisableReasonsChanged( + const std::string& extension_id, + int disabled_reasons) { + CheckExitCondition(); +} + +void AppsStatusChangeChecker::OnExtensionRegistered( + const std::string& extension_id, + const base::Time& install_time, + bool is_enabled) { + CheckExitCondition(); +} + +void AppsStatusChangeChecker::OnExtensionPrefsLoaded( + const std::string& extension_id, + const extensions::ExtensionPrefs* prefs) { + CheckExitCondition(); +} + +void AppsStatusChangeChecker::OnExtensionPrefsDeleted( + const std::string& extension_id) { + CheckExitCondition(); +} + +void AppsStatusChangeChecker::OnExtensionStateChanged( + const std::string& extension_id, + bool state) { + CheckExitCondition(); +} + +void AppsStatusChangeChecker::OnAppsReordered( + const absl::optional<std::string>& extension_id) { + CheckExitCondition(); +} + +AppsMatchChecker::AppsMatchChecker() = default; + bool AppsMatchChecker::IsExitConditionSatisfied(std::ostream* os) { *os << "Waiting for apps to match"; @@ -302,63 +367,3 @@ } return true; } - -void AppsMatchChecker::OnExtensionLoaded( - content::BrowserContext* context, - const extensions::Extension* extension) { - CheckExitCondition(); -} - -void AppsMatchChecker::OnExtensionUnloaded( - content::BrowserContext* context, - const extensions::Extension* extension, - extensions::UnloadedExtensionReason reason) { - CheckExitCondition(); -} - -void AppsMatchChecker::OnExtensionInstalled( - content::BrowserContext* browser_context, - const extensions::Extension* extension, - bool is_update) { - CheckExitCondition(); -} - -void AppsMatchChecker::OnExtensionUninstalled( - content::BrowserContext* browser_context, - const extensions::Extension* extension, - extensions::UninstallReason reason) { - CheckExitCondition(); -} - -void AppsMatchChecker::OnExtensionDisableReasonsChanged( - const std::string& extension_id, - int disabled_reasons) { - CheckExitCondition(); -} - -void AppsMatchChecker::OnExtensionRegistered(const std::string& extension_id, - const base::Time& install_time, - bool is_enabled) { - CheckExitCondition(); -} - -void AppsMatchChecker::OnExtensionPrefsLoaded( - const std::string& extension_id, - const extensions::ExtensionPrefs* prefs) { - CheckExitCondition(); -} - -void AppsMatchChecker::OnExtensionPrefsDeleted( - const std::string& extension_id) { - CheckExitCondition(); -} - -void AppsMatchChecker::OnExtensionStateChanged(const std::string& extension_id, - bool state) { - CheckExitCondition(); -} - -void AppsMatchChecker::OnAppsReordered( - const absl::optional<std::string>& extension_id) { - CheckExitCondition(); -}
diff --git a/chrome/browser/sync/test/integration/apps_helper.h b/chrome/browser/sync/test/integration/apps_helper.h index 9ded9eb..f14e0ae 100644 --- a/chrome/browser/sync/test/integration/apps_helper.h +++ b/chrome/browser/sync/test/integration/apps_helper.h
@@ -114,23 +114,20 @@ void AwaitWebAppQuiescence(std::vector<Profile*> profiles); } // namespace apps_helper -// Checker to block for a set of profiles to have matching extensions lists. If -// the verifier profile is enabled, it will be included in the set of profiles -// to check against. -class AppsMatchChecker : public StatusChangeChecker, - public extensions::ExtensionRegistryObserver, - public extensions::ExtensionPrefsObserver, - public extensions::InstallObserver { +// An app specific version of StatusChangeChecker which checks the exit +// condition on all extension app events. Subclasses must override +// IsExitConditionSatisfied() with their desired check. +class AppsStatusChangeChecker : public StatusChangeChecker, + public extensions::ExtensionRegistryObserver, + public extensions::ExtensionPrefsObserver, + public extensions::InstallObserver { public: - AppsMatchChecker(); + AppsStatusChangeChecker(); - AppsMatchChecker(const AppsMatchChecker&) = delete; - AppsMatchChecker& operator=(const AppsMatchChecker&) = delete; + AppsStatusChangeChecker(const AppsStatusChangeChecker&) = delete; + AppsStatusChangeChecker& operator=(const AppsStatusChangeChecker&) = delete; - ~AppsMatchChecker() override; - - // StatusChangeChecker implementation. - bool IsExitConditionSatisfied(std::ostream* os) override; + ~AppsStatusChangeChecker() override; // extensions::ExtensionRegistryObserver implementation. void OnExtensionLoaded(content::BrowserContext* context, @@ -161,9 +158,10 @@ void OnAppsReordered( const absl::optional<std::string>& extension_id) override; - private: + protected: std::vector<Profile*> profiles_; + private: content::NotificationRegistrar registrar_; // This installs apps, too. @@ -175,4 +173,15 @@ install_tracker_observation_{this}; }; +// Checker to block for a set of profiles to have matching extensions lists. If +// the verifier profile is enabled, it will be included in the set of profiles +// to check against. +class AppsMatchChecker : public AppsStatusChangeChecker { + public: + AppsMatchChecker(); + + // StatusChangeChecker implementation. + bool IsExitConditionSatisfied(std::ostream* os) override; +}; + #endif // CHROME_BROWSER_SYNC_TEST_INTEGRATION_APPS_HELPER_H_
diff --git a/chrome/browser/sync/test/integration/two_client_extension_apps_sync_test.cc b/chrome/browser/sync/test/integration/two_client_extension_apps_sync_test.cc index 1b982b2..a5a13b4e 100644 --- a/chrome/browser/sync/test/integration/two_client_extension_apps_sync_test.cc +++ b/chrome/browser/sync/test/integration/two_client_extension_apps_sync_test.cc
@@ -8,6 +8,7 @@ #include "base/bind.h" #include "base/strings/utf_string_conversions.h" +#include "base/test/metrics/histogram_tester.h" #include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/extensions/extension_sync_data.h" #include "chrome/browser/extensions/extension_sync_service.h" @@ -15,8 +16,11 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/test/integration/apps_helper.h" #include "chrome/browser/sync/test/integration/sync_app_helper.h" +#include "chrome/browser/sync/test/integration/sync_datatype_helper.h" #include "chrome/browser/sync/test/integration/sync_integration_test_util.h" #include "chrome/browser/sync/test/integration/sync_test.h" +#include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h" +#include "chrome/browser/web_applications/web_app_helpers.h" #include "chrome/browser/web_applications/web_app_install_info.h" #include "chrome/common/extensions/manifest_handlers/app_launch_info.h" #include "components/sync/model/string_ordinal.h" @@ -27,6 +31,7 @@ #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" +#include "extensions/browser/test_extension_registry_observer.h" #include "extensions/common/constants.h" using apps_helper::AllProfilesHaveSameApps; @@ -379,6 +384,69 @@ ASSERT_TRUE(AppsMatchChecker().Wait()); } +namespace { +constexpr char kHostedAppId0[] = "afbaddhaooeepnpckmnneeficocjkjlg"; +constexpr char kHostedAppId1[] = "gommgmjfjblhnpfknedcgjfphgkfcpip"; +} // namespace + +IN_PROC_BROWSER_TEST_F(TwoClientExtensionAppsSyncTest, + DefaultWebAppMigratedChromeAppSyncBlocked) { + base::HistogramTester histogram_tester; + + // Inject web app migration for kHostedApp0. + web_app::ScopedTestingPreinstalledAppData preinstalled_app_data; + { + const GURL kStartUrl = GURL("https://www.example.com/start_url"); + const web_app::AppId kWebAppId = + web_app::GenerateAppId(absl::nullopt, kStartUrl); + web_app::ExternalInstallOptions options( + GURL("https://www.example.com/install_url"), + web_app::DisplayMode::kStandalone, + web_app::ExternalInstallSource::kExternalDefault); + options.user_type_allowlist = {"unmanaged"}; + options.uninstall_and_replace = {kHostedAppId0}; + options.only_use_app_info_factory = true; + options.app_info_factory = base::BindRepeating( + [](GURL start_url) { + auto info = std::make_unique<WebAppInstallInfo>(); + info->title = u"Test app"; + info->start_url = start_url; + return info; + }, + kStartUrl); + options.expected_app_id = kWebAppId; + preinstalled_app_data.apps = {std::move(options)}; + } + + // Profiles must be created after test migration config is set. + ASSERT_TRUE(SetupSync()); + + // Add kHostedApp0 to sync profile and let it sync across. + ASSERT_EQ(InstallHostedApp(GetProfile(0), 0), kHostedAppId0); + ASSERT_TRUE(AwaitQuiescence()); + + // kHostedApp0 should be blocked by the web app migration config. + histogram_tester.ExpectUniqueSample( + "Extensions.SyncBlockedByDefaultWebAppMigration", true, 1); + + // Add kHostedApp1 and let it sync install. This should give kHostedApp0 + // enough time to install in case it wasn't actually blocked. This is + // technically racy as the installs could complete in any order but it's + // unlikely given the headstart kHostedApp0 got. + ASSERT_EQ(InstallHostedApp(GetProfile(0), 1), kHostedAppId1); + struct HostedApp1Installed : public AppsStatusChangeChecker { + bool IsExitConditionSatisfied(std::ostream* os) override { + return GetExtensionRegistry(sync_datatype_helper::test()->GetProfile(1)) + ->enabled_extensions() + .Contains(kHostedAppId1); + } + }; + ASSERT_TRUE(HostedApp1Installed().Wait()); + EXPECT_FALSE(GetExtensionRegistry(GetProfile(1)) + ->enabled_extensions() + .Contains(kHostedAppId0)); +} + // TODO(akalin): Add tests exercising: // - Offline installation/uninstallation behavior // - App-specific properties
diff --git a/chrome/browser/themes/theme_service_browsertest.cc b/chrome/browser/themes/theme_service_browsertest.cc index 49db6e1..8c228ef 100644 --- a/chrome/browser/themes/theme_service_browsertest.cc +++ b/chrome/browser/themes/theme_service_browsertest.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/themes/theme_properties.h" #include "chrome/browser/themes/theme_service_factory.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_window.h" #include "chrome/common/pref_names.h" #include "components/prefs/pref_service.h" #include "content/public/test/browser_test.h" @@ -49,13 +50,13 @@ IN_PROC_BROWSER_TEST_F(ThemeServiceBrowserTest, PRE_ThemeDataPackInvalid) { Profile* profile = browser()->profile(); ThemeService* theme_service = ThemeServiceFactory::GetForProfile(profile); - const ui::ThemeProvider& theme_provider = - ThemeService::GetThemeProviderForProfile(profile); + const ui::ThemeProvider* theme_provider = + browser()->window()->GetThemeProvider(); // Test initial state. EXPECT_FALSE(UsingCustomTheme(*theme_service)); EXPECT_NE(kThemeNtpLinkColor, - theme_provider.GetColor(ThemeProperties::COLOR_NTP_LINK)); + theme_provider->GetColor(ThemeProperties::COLOR_NTP_LINK)); EXPECT_EQ(base::FilePath(), profile->GetPrefs()->GetFilePath(prefs::kCurrentThemePackFilename)); @@ -66,7 +67,7 @@ // Check that the theme was installed. EXPECT_TRUE(UsingCustomTheme(*theme_service)); EXPECT_EQ(kThemeNtpLinkColor, - theme_provider.GetColor(ThemeProperties::COLOR_NTP_LINK)); + theme_provider->GetColor(ThemeProperties::COLOR_NTP_LINK)); EXPECT_NE(base::FilePath(), profile->GetPrefs()->GetFilePath(prefs::kCurrentThemePackFilename)); @@ -80,11 +81,11 @@ IN_PROC_BROWSER_TEST_F(ThemeServiceBrowserTest, ThemeDataPackInvalid) { ThemeService* theme_service = ThemeServiceFactory::GetForProfile( browser()->profile()); - const ui::ThemeProvider& theme_provider = - ThemeService::GetThemeProviderForProfile(browser()->profile()); + const ui::ThemeProvider* theme_provider = + browser()->window()->GetThemeProvider(); EXPECT_TRUE(UsingCustomTheme(*theme_service)); EXPECT_EQ(kThemeNtpLinkColor, - theme_provider.GetColor(ThemeProperties::COLOR_NTP_LINK)); + theme_provider->GetColor(ThemeProperties::COLOR_NTP_LINK)); } } // namespace
diff --git a/chrome/browser/touch_to_fill/android/internal/BUILD.gn b/chrome/browser/touch_to_fill/android/internal/BUILD.gn index d931bdd..bb59c32 100644 --- a/chrome/browser/touch_to_fill/android/internal/BUILD.gn +++ b/chrome/browser/touch_to_fill/android/internal/BUILD.gn
@@ -32,11 +32,17 @@ "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillCoordinator.java", "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillMediator.java", "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillProperties.java", + "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillResourceProvider.java", + "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillResourceProviderImpl.java", "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillView.java", "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewBinder.java", "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillViewHolder.java", ] + # Add the actual implementation where necessary so that downstream targets + # can provide their own implementations. + jar_excluded_patterns = [ "*/TouchToFillResourceProviderImpl.class" ] + resources_package = "org.chromium.chrome.browser.touch_to_fill" annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ] } @@ -68,3 +74,15 @@ android_bundle_locales_as_resources, [ "values-{{source_name_part}}/android_touch_to_fill_strings.xml" ]) } + +android_library("resource_provider_public_impl_java") { + sources = [ "java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillResourceProviderImpl.java" ] + + deps = [ + ":java", + ":java_resources", + "//third_party/androidx:androidx_annotation_annotation_java", + ] + + resources_package = "org.chromium.chrome.browser.touch_to_fill" +}
diff --git a/chrome/browser/touch_to_fill/android/internal/README.md b/chrome/browser/touch_to_fill/android/internal/README.md index 1823c1e..8895e1c 100644 --- a/chrome/browser/touch_to_fill/android/internal/README.md +++ b/chrome/browser/touch_to_fill/android/internal/README.md
@@ -82,6 +82,12 @@ the model accordingly. Interactions with the view are typically handled here and either affect the model or notify callers of the component API. +Additional **TouchToFillResourceProvider** is used to select resources with any +non-trivial logic that determines actual resource file/ID. It also allows overriding +the selection logic by providing a different downstream implementation. +Upstream implementation is defined in `TouchToFillResourceProviderImpl`. +To support downstream overrides, corresponding build target is listed as dependency +in `//chrome/android/BUILD.gn`, but have no any usages outside of this package. ## View
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillResourceProvider.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillResourceProvider.java new file mode 100644 index 0000000..83f7222 --- /dev/null +++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillResourceProvider.java
@@ -0,0 +1,20 @@ +// Copyright 2022 The Chromium 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.touch_to_fill; + +import androidx.annotation.DrawableRes; + +/** + * Provides functions that choose the correct resource id for touch-to-fill UI. + * Needed to differentiate upstream and downstream resources. + * This exists to ensure all implementations of TouchToFillResourceProviderImpl + * provide the same set of methods. + */ +interface TouchToFillResourceProvider { + /** + * Returns the drawable id to be displayed as a bottom sheet header image. + */ + public @DrawableRes int getHeaderImageDrawableId(); +}
diff --git a/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillResourceProviderImpl.java b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillResourceProviderImpl.java new file mode 100644 index 0000000..038eb4a --- /dev/null +++ b/chrome/browser/touch_to_fill/android/internal/java/src/org/chromium/chrome/browser/touch_to_fill/TouchToFillResourceProviderImpl.java
@@ -0,0 +1,18 @@ +// Copyright 2022 The Chromium 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.touch_to_fill; + +import androidx.annotation.DrawableRes; + +/** + * Public version of {@link TouchToFillResourceProviderImpl}. + * Downstream could provide a different implementation. + */ +class TouchToFillResourceProviderImpl implements TouchToFillResourceProvider { + @Override + public @DrawableRes int getHeaderImageDrawableId() { + return R.drawable.touch_to_fill_header_image; + } +}
diff --git a/chrome/browser/ui/BUILD.gn b/chrome/browser/ui/BUILD.gn index 31b9fed..25e2b47 100644 --- a/chrome/browser/ui/BUILD.gn +++ b/chrome/browser/ui/BUILD.gn
@@ -1463,6 +1463,10 @@ "webui/extensions/extensions_ui.h", "webui/favicon_source.cc", "webui/favicon_source.h", + "webui/feed/feed_ui.cc", + "webui/feed/feed_ui.h", + "webui/feed/feed_ui_config.cc", + "webui/feed/feed_ui_config.h", "webui/feedback/child_web_dialog.cc", "webui/feedback/child_web_dialog.h", "webui/feedback/feedback_dialog.cc", @@ -4628,6 +4632,8 @@ "views/tabs/tab_animation_state.h", "views/tabs/tab_close_button.cc", "views/tabs/tab_close_button.h", + "views/tabs/tab_container.cc", + "views/tabs/tab_container.h", "views/tabs/tab_controller.h", "views/tabs/tab_drag_context.h", "views/tabs/tab_drag_controller.cc", @@ -5120,6 +5126,8 @@ "extensions/extension_removal_watcher.h", "extensions/extension_settings_overridden_dialog.cc", "extensions/extension_settings_overridden_dialog.h", + "extensions/extension_site_access_combobox_model.cc", + "extensions/extension_site_access_combobox_model.h", "extensions/extensions_container.h", "extensions/hosted_app_browser_controller.cc", "extensions/hosted_app_browser_controller.h",
diff --git a/chrome/browser/ui/android/context_menu_helper.cc b/chrome/browser/ui/android/context_menu_helper.cc index 981068ca..2ccd0d9 100644 --- a/chrome/browser/ui/android/context_menu_helper.cc +++ b/chrome/browser/ui/android/context_menu_helper.cc
@@ -68,6 +68,11 @@ view->content_offset() * view->GetDipScale()); } +void ContextMenuHelper::DismissContextMenu() { + JNIEnv* env = base::android::AttachCurrentThread(); + Java_ContextMenuHelper_dismissContextMenu(env, java_obj_); +} + void ContextMenuHelper::OnContextMenuClosed( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj) {
diff --git a/chrome/browser/ui/android/context_menu_helper.h b/chrome/browser/ui/android/context_menu_helper.h index bcce3236c..4a897c0 100644 --- a/chrome/browser/ui/android/context_menu_helper.h +++ b/chrome/browser/ui/android/context_menu_helper.h
@@ -29,6 +29,8 @@ void ShowContextMenu(content::RenderFrameHost& render_frame_host, const content::ContextMenuParams& params); + void DismissContextMenu(); + void OnContextMenuClosed(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd index 048b7c57..dff5e86 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -3205,7 +3205,7 @@ <!-- Feature notification guide --> <message name="IDS_FEATURE_NOTIFICATION_GUIDE_NOTIFICATION_TITLE" desc="Notification title text educating user about tips and tricks in chrome."> - Chrome tips: + Chrome tips </message> <message name="IDS_FEATURE_NOTIFICATION_GUIDE_NOTIFICATION_MESSAGE_DEFAULT_BROWSER" desc="Notification body text educating user about setting chrome as default browser."> Learn how to set chrome as your default @@ -5160,6 +5160,10 @@ Creating GIF <ph name="PERCENT">%1$d<ex>13</ex></ph>%% </message> + <message name="IDS_LIGHTWEIGHT_REACTIONS_CREATING_GIF_ANNOUNCEMENT" is_accessibility_with_no_ui="true" desc="The accessibility text to read when GIF creation begins."> + Creating GIF + </message> + <message name="IDS_LIGHTWEIGHT_REACTIONS_TOOLBAR_ANNOUNCEMENT" is_accessibility_with_no_ui="true" desc="The accessibility text to read when the lightweight reactions toolbar is selected. The user can then select a reaction from the toolbar to place on the screen."> Choose an emotion </message> @@ -5384,14 +5388,11 @@ </message> <!-- WebID Account Selection strings --> - <message name="IDS_ACCOUNT_SELECTION_SHEET_TITLE_SINGLE" desc="Header for Account Selection sheet where the user only has a single account to sign up with." translateable="false"> - Sign in to <ph name="SITE_NAME">%1$s<ex>rp.example</ex></ph> + <message name="IDS_ACCOUNT_SELECTION_SHEET_TITLE_AUTO" desc="Header for sign in sheet. Sheet is shown to inform user of sign in. Sign in occurs automatically. (User can cancel)." translateable="false"> + Signing in to <ph name="SITE_NAME">%1$s<ex>rp.example</ex></ph> with <ph name="IDENTITY_PROVIDER_URL">%2$s<ex>idp.com</ex></ph> </message> - <message name="IDS_ACCOUNT_SELECTION_SHEET_TITLE" desc="Header for Account Selection sheet where the user can pick an account to sign up with." translateable="false"> - Choose an account for <ph name="SITE_NAME">%1$s<ex>rp.example</ex></ph> - </message> - <message name="IDS_ACCOUNT_SELECTION_SHEET_IDP_SUBHEADER" desc="Sub-heading for Account Selection sheet where user can pick an account to sign up with." translateable="false"> - with <ph name="IDENTITY_PROVIDER_URL">%1$s<ex>idp.com</ex></ph> + <message name="IDS_ACCOUNT_SELECTION_SHEET_TITLE_EXPLICIT" desc="Header for sign in sheet. Sheet is shown to prompt user for sign in consent." translateable="false"> + Sign in to <ph name="SITE_NAME">%1$s<ex>rp.example</ex></ph> with <ph name="IDENTITY_PROVIDER_URL">%2$s<ex>idp.com</ex></ph> </message> <message name="IDS_ACCOUNT_SELECTION_DATA_SHARING_CONSENT_NO_LINKS" desc="The consent text shown to the user before sign up." translateable="false"> To continue, <ph name="PROVIDER_NAME">%1$s<ex>provider.example</ex></ph> will share your name, email, address, and profile picture with this site. @@ -5415,9 +5416,6 @@ <message name="IDS_ACCOUNT_SELECTION_SHEET_CLOSED" desc="Accessibility string read when the Account Selection bottom sheet showing a list of the user's accounts is closed." translateable="false"> List of accounts to be selected is closed. </message> - <message name="IDS_SIGN_IN_SHEET_TITLE" desc="Header for sign in sheet." translateable="false"> - Sign in to <ph name="SITE_NAME">%1$s<ex>rp.example</ex></ph> - </message> <message name="IDS_VERIFY_SHEET_TITLE" desc="Header for verify sheet." translateable="false"> Verifying… </message>
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_FEATURE_NOTIFICATION_GUIDE_NOTIFICATION_TITLE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_FEATURE_NOTIFICATION_GUIDE_NOTIFICATION_TITLE.png.sha1 index 094cfe908..ca700cb 100644 --- a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_FEATURE_NOTIFICATION_GUIDE_NOTIFICATION_TITLE.png.sha1 +++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_FEATURE_NOTIFICATION_GUIDE_NOTIFICATION_TITLE.png.sha1
@@ -1 +1 @@ -5630d298d323d03cdcb3cb95b8931d26b0aad86a \ No newline at end of file +5f21856079427683fb4a964d4291d586615e024e \ No newline at end of file
diff --git a/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.cc b/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.cc index b94f59eb..79f6096 100644 --- a/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.cc +++ b/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.cc
@@ -37,6 +37,14 @@ helper->ShowContextMenu(render_frame_host, params); } +void ChromeWebContentsViewDelegateAndroid::DismissContextMenu() { + // ContextMenuHelper is a WebContentsUserData, so it will be the same obj used + // in #ShowContextMenu(). + ContextMenuHelper* helper = ContextMenuHelper::FromWebContents(web_contents_); + if (helper) + helper->DismissContextMenu(); +} + content::WebContentsViewDelegate* CreateWebContentsViewDelegate( content::WebContents* web_contents) { return new ChromeWebContentsViewDelegateAndroid(web_contents);
diff --git a/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.h b/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.h index 538145e..3c04611 100644 --- a/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.h +++ b/chrome/browser/ui/android/tab_contents/chrome_web_contents_view_delegate_android.h
@@ -32,6 +32,9 @@ const content::ContextMenuParams& params) override; // WebContentsViewDelegate: + void DismissContextMenu() override; + + // WebContentsViewDelegate: content::WebDragDestDelegate* GetDragDestDelegate() override; private:
diff --git a/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_account_item.xml b/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_account_item.xml index 7668de0..54a65b8 100644 --- a/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_account_item.xml +++ b/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_account_item.xml
@@ -8,13 +8,16 @@ android:descendantFocusability="blocksDescendants" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginBottom="6dp" + android:layout_marginBottom="@dimen/account_selection_sheet_item_padding" + android:layout_marginTop="@dimen/account_selection_sheet_item_padding" android:gravity="center_vertical" android:orientation="horizontal"> <org.chromium.ui.widget.ChromeImageView android:id="@+id/start_icon" - android:layout_marginEnd="10dp" + android:layout_width="@dimen/account_selection_account_avatar_size" + android:layout_height="@dimen/account_selection_account_avatar_size" + android:layout_marginEnd="16dp" style="@style/ListItemStartIcon" /> <LinearLayout @@ -30,7 +33,7 @@ android:layout_height="wrap_content" android:maxLines="1" android:ellipsize="end" - android:textAppearance="@style/TextAppearance.TextLarge.Primary" /> + android:textAppearance="@style/TextAppearance.TextMedium.Primary" /> <TextView android:id="@+id/description"
diff --git a/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_data_sharing_consent_item.xml b/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_data_sharing_consent_item.xml index 114655c..013d28b 100644 --- a/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_data_sharing_consent_item.xml +++ b/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_data_sharing_consent_item.xml
@@ -10,7 +10,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" + android:layout_marginBottom="@dimen/account_selection_sheet_item_padding" + android:layout_marginTop="@dimen/account_selection_sheet_item_padding" android:gravity="start" - android:textAppearance="@style/TextAppearance.TextMedium.Secondary" - android:minHeight="@dimen/account_selection_sheet_title_height" - android:layout_marginBottom="@dimen/account_selection_sheet_title_margin_bottom"/> + android:textAppearance="@style/TextAppearance.TextSmall.Secondary" + android:minHeight="@dimen/account_selection_sheet_title_height"/>
diff --git a/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_header_item.xml b/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_header_item.xml index 2abbf10..5a4bcd6a 100644 --- a/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_header_item.xml +++ b/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_header_item.xml
@@ -10,34 +10,41 @@ xmlns:app="http://schemas.android.com/apk/res-auto" android:layout_width="match_parent" android:layout_height="wrap_content" - android:layout_marginTop="12dp" - android:layout_marginBottom="16dp" + android:layout_marginTop="4dp" android:layout_gravity="top" - android:orientation="horizontal" - android:minHeight="@dimen/account_selection_sheet_title_height"> - <LinearLayout - android:layout_width="0dp" - android:layout_height="wrap_content" - android:layout_weight="1" - android:layout_gravity="start" - android:orientation="vertical"> - <org.chromium.ui.widget.TextViewWithLeading - android:id="@+id/header_title" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.Headline.Primary"/> - <TextView - android:id="@+id/header_idp_url" - android:layout_width="match_parent" - android:layout_height="wrap_content" - android:textAppearance="@style/TextAppearance.TextMedium.Secondary" /> + android:orientation="vertical"> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="top" + android:orientation="horizontal" + android:minHeight="@dimen/account_selection_sheet_title_height"> + <org.chromium.ui.widget.ChromeImageView + android:id="@+id/header_idp_icon" + android:layout_width="24dp" + android:layout_height="24dp" + android:layout_gravity="center_vertical" + android:layout_marginEnd="16dp" + android:visibility="gone" /> + <TextView + android:id="@+id/header_title" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_weight="1" + android:layout_gravity="center_vertical" + android:textAppearance="@style/TextAppearance.TextAccentMediumThick" /> + <org.chromium.ui.widget.ChromeImageButton + android:id="@+id/close_button" + android:layout_height="48dp" + android:layout_width="48dp" + android:background="?attr/selectableItemBackground" + android:contentDescription="@string/close" + android:scaleType="center" + android:src="@drawable/btn_close" /> </LinearLayout> - <org.chromium.ui.widget.ChromeImageButton - android:id="@+id/close_button" - android:layout_height="48dp" - android:layout_width="48dp" - android:background="?attr/selectableItemBackground" - android:contentDescription="@string/close" - android:scaleType="center" - android:src="@drawable/btn_close" /> + <View + android:background="@macro/divider_line_bg_color" + android:layout_height="1dp" + android:layout_width="match_parent" + android:layout_marginBottom="8dp"/> </LinearLayout>
diff --git a/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_sheet.xml b/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_sheet.xml index 5b4bddf2..5db34c46 100644 --- a/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_sheet.xml +++ b/chrome/browser/ui/android/webid/internal/java/res/layout/account_selection_sheet.xml
@@ -19,7 +19,7 @@ android:layout_marginEnd="@dimen/account_selection_sheet_horizontal_margin" android:layout_marginStart="@dimen/account_selection_sheet_horizontal_margin" android:clipToPadding="false" - android:paddingBottom="@dimen/account_selection_sheet_item_padding_bottom" + android:paddingBottom="8dp" android:divider="@null" tools:listitem="@layout/account_selection_account_item"/> </LinearLayout>
diff --git a/chrome/browser/ui/android/webid/internal/java/res/values/dimens.xml b/chrome/browser/ui/android/webid/internal/java/res/values/dimens.xml index 92b0588..781f798 100644 --- a/chrome/browser/ui/android/webid/internal/java/res/values/dimens.xml +++ b/chrome/browser/ui/android/webid/internal/java/res/values/dimens.xml
@@ -4,16 +4,16 @@ found in the LICENSE file. --> <resources> - <dimen name="account_selection_sheet_horizontal_margin">16dp</dimen> + <dimen name="account_selection_sheet_horizontal_margin">24dp</dimen> <dimen name="account_selection_sheet_title_height">32dp</dimen> - <dimen name="account_selection_sheet_title_margin_bottom">8dp</dimen> - <dimen name="account_selection_sheet_item_padding_bottom">8dp</dimen> + <dimen name="account_selection_sheet_item_padding">10dp</dimen> - <dimen name="account_selection_favicon_border_size">1dp</dimen> + <dimen name="account_selection_account_avatar_size">40dp</dimen> + <dimen name="account_selection_account_avatar_monogram_text_size">16dp</dimen> - <dimen name="account_selection_sheet_button_margin">2dp</dimen> + <dimen name="account_selection_sheet_button_margin">4dp</dimen> <dimen name="account_selection_continue_icon_size">24dp</dimen> </resources>
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java index f3694b1..0cc32de 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionControllerTest.java
@@ -6,7 +6,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -14,6 +13,7 @@ import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -22,8 +22,9 @@ import static org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.AccountProperties.ACCOUNT; import static org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.AccountProperties.AVATAR; -import static org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.AccountProperties.FAVICON_OR_FALLBACK; +import static org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.HeaderProperties.FORMATTED_IDP_URL; import static org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.HeaderProperties.FORMATTED_RP_URL; +import static org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.HeaderProperties.IDP_BRAND_ICON; import static org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.HeaderProperties.TYPE; import android.graphics.Bitmap; @@ -36,7 +37,6 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.robolectric.annotation.Config; @@ -48,7 +48,6 @@ import org.chromium.base.test.util.JniMocker; import org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.AccountProperties; import org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.AccountProperties.Avatar; -import org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.AccountProperties.FaviconOrFallback; import org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.AutoSignInCancelButtonProperties; import org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.ContinueButtonProperties; import org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.DataSharingConsentProperties; @@ -58,14 +57,13 @@ import org.chromium.chrome.browser.ui.android.webid.data.ClientIdMetadata; import org.chromium.chrome.browser.ui.android.webid.data.IdentityProviderMetadata; import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; -import org.chromium.components.favicon.IconType; -import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.image_fetcher.ImageFetcher; import org.chromium.components.url_formatter.SchemeDisplay; import org.chromium.components.url_formatter.UrlFormatter; import org.chromium.components.url_formatter.UrlFormatterJni; import org.chromium.ui.modelutil.MVCListAdapter.ListItem; import org.chromium.ui.modelutil.MVCListAdapter.ModelList; +import org.chromium.ui.modelutil.PropertyModel; import org.chromium.url.GURL; import org.chromium.url.JUnitTestGURLs; @@ -99,14 +97,15 @@ private static final Account NEW_USER = new Account("602214076", "goto@email.example", "Sam E. Goto", "Sam", TEST_PROFILE_PIC, /*isSignIn=*/false); - private static final IdentityProviderMetadata IDP_METADATA = - new IdentityProviderMetadata(Color.BLACK, Color.BLACK, null); private static final ClientIdMetadata CLIENT_ID_METADATA = new ClientIdMetadata(TEST_URL_TERMS_OF_SERVICE, TEST_URL_PRIVACY_POLICY); - private static final @Px int DESIRED_FAVICON_SIZE = 64; private static final @Px int DESIRED_AVATAR_SIZE = 100; + // Needs Bitmap.class Mockito mock for initialization. Initialized in + // AccountSelectionControllerTest constructor. + public final IdentityProviderMetadata IDP_METADATA; + @Rule public JniMocker mJniMocker = new JniMocker(); @Mock @@ -114,23 +113,21 @@ @Mock private AccountSelectionComponent.Delegate mMockDelegate; @Mock - private LargeIconBridge mMockIconBridge; - @Mock private ImageFetcher mMockImageFetcher; @Mock private BottomSheetController mMockBottomSheetController; - // Can't be local, as it has to be initialized by initMocks. - @Captor - private ArgumentCaptor<LargeIconBridge.LargeIconCallback> mCallbackArgumentCaptor; - private AccountSelectionBottomSheetContent mBottomSheetContent; private AccountSelectionMediator mMediator; private final ModelList mSheetItems = new ModelList(); + public AccountSelectionControllerTest() { + MockitoAnnotations.initMocks(this); + IDP_METADATA = new IdentityProviderMetadata(Color.BLACK, Color.BLACK, mock(Bitmap.class)); + } + @Before public void setUp() { - MockitoAnnotations.initMocks(this); mJniMocker.mock(UrlFormatterJni.TEST_HOOKS, mUrlFormatterJniMock); when(mUrlFormatterJniMock.formatUrlForDisplayOmitScheme(anyString())) .then(inv -> format(inv.getArgument(0))); @@ -142,84 +139,39 @@ .then(inv -> formatForSecurityDisplay(((GURL) inv.getArgument(0)))); mBottomSheetContent = new AccountSelectionBottomSheetContent(null, null); - mMediator = new AccountSelectionMediator(mMockDelegate, mSheetItems, - mMockBottomSheetController, mBottomSheetContent, mMockImageFetcher, - DESIRED_AVATAR_SIZE, mMockIconBridge, DESIRED_FAVICON_SIZE); + mMediator = + new AccountSelectionMediator(mMockDelegate, mSheetItems, mMockBottomSheetController, + mBottomSheetContent, mMockImageFetcher, DESIRED_AVATAR_SIZE); } @Test - public void testShowAccountsCreatesHeader() { - mMediator.showAccounts(TEST_URL, TEST_URL_1, Arrays.asList(ANA, BOB), IDP_METADATA, - CLIENT_ID_METADATA, false); - assertEquals("Incorrect header type", ItemType.HEADER, mSheetItems.get(0).type); - assertNotEquals("Incorrect header multiple accounts", HeaderType.SINGLE_ACCOUNT, - mSheetItems.get(0).model.get(TYPE)); - assertEquals("Incorrect header url", formatForSecurityDisplay(TEST_URL), - mSheetItems.get(0).model.get(FORMATTED_RP_URL)); + public void testShowAccountSignInHeader() { + mMediator.showAccounts(TEST_URL, TEST_URL_1, Arrays.asList(ANA), IDP_METADATA, + CLIENT_ID_METADATA, false /* isAutoSignIn */); + + assertEquals(ItemType.HEADER, mSheetItems.get(0).type); + PropertyModel headerModel = mSheetItems.get(0).model; + assertEquals(HeaderType.SIGN_IN, headerModel.get(TYPE)); + assertEquals(formatForSecurityDisplay(TEST_URL), headerModel.get(FORMATTED_RP_URL)); + assertEquals(formatForSecurityDisplay(TEST_URL_1), headerModel.get(FORMATTED_IDP_URL)); + assertNotNull(headerModel.get(IDP_BRAND_ICON)); } @Test - public void testShowAccountWithSingleEntryCreatesSignUpHeader() { + public void testShowAccountSignUpHeader() { mMediator.showAccounts(TEST_URL, TEST_URL_1, Arrays.asList(NEW_USER), IDP_METADATA, - CLIENT_ID_METADATA, false); - assertEquals("Incorrect header type", ItemType.HEADER, mSheetItems.get(0).type); - assertEquals("Incorrect header single account", HeaderType.SINGLE_ACCOUNT, - mSheetItems.get(0).model.get(TYPE)); - assertEquals("Incorrect header url", formatForSecurityDisplay(TEST_URL), - mSheetItems.get(0).model.get(FORMATTED_RP_URL)); + CLIENT_ID_METADATA, false /* isAutoSignIn */); + + assertEquals(ItemType.HEADER, mSheetItems.get(0).type); + assertEquals(HeaderType.SIGN_IN, mSheetItems.get(0).model.get(TYPE)); } @Test - public void testShowAccountWithSingleEntryCreatesSignInHeader() { - mMediator.showAccounts( - TEST_URL, TEST_URL_1, Arrays.asList(ANA), IDP_METADATA, CLIENT_ID_METADATA, false); - assertEquals("Incorrect header type", ItemType.HEADER, mSheetItems.get(0).type); - assertEquals("Incorrect header single account", HeaderType.SIGN_IN, - mSheetItems.get(0).model.get(TYPE)); - assertEquals("Incorrect header url", formatForSecurityDisplay(TEST_URL), - mSheetItems.get(0).model.get(FORMATTED_RP_URL)); - } - - @Test - public void testShowAccountWithMultipleEntriesCreatesSignUpHeader() { - mMediator.showAccounts(TEST_URL, TEST_URL_1, Arrays.asList(NEW_USER, NEW_USER), - IDP_METADATA, CLIENT_ID_METADATA, false); - assertEquals("Incorrect header type", ItemType.HEADER, mSheetItems.get(0).type); - assertEquals("Incorrect header single account", HeaderType.MULTIPLE_ACCOUNT, - mSheetItems.get(0).model.get(TYPE)); - assertEquals("Incorrect header url", formatForSecurityDisplay(TEST_URL), - mSheetItems.get(0).model.get(FORMATTED_RP_URL)); - } - - @Test - public void testShowAccountWithMultipleEntriesCreatesSignInHeader() { - mMediator.showAccounts(TEST_URL, TEST_URL_1, Arrays.asList(ANA, NEW_USER), IDP_METADATA, - CLIENT_ID_METADATA, false); - assertEquals("Incorrect header type", ItemType.HEADER, mSheetItems.get(0).type); - assertEquals("Incorrect header single account", HeaderType.SIGN_IN, - mSheetItems.get(0).model.get(TYPE)); - assertEquals("Incorrect header url", formatForSecurityDisplay(TEST_URL), - mSheetItems.get(0).model.get(FORMATTED_RP_URL)); - } - - @Test - public void testShowAccountsSetsAccountListAndRequestsFavicons() { - mMediator.showAccounts(TEST_URL, TEST_URL_1, Arrays.asList(ANA, CARL, BOB), IDP_METADATA, - CLIENT_ID_METADATA, false); - assertEquals( - "Incorrect item sheet count", 4, mSheetItems.size()); // Header + three Accounts - assertEquals("Incorrect type", ItemType.ACCOUNT, mSheetItems.get(1).type); - assertEquals("Incorrect account", ANA, mSheetItems.get(1).model.get(ACCOUNT)); - assertNull(mSheetItems.get(1).model.get(FAVICON_OR_FALLBACK)); - assertEquals("Incorrect type", ItemType.ACCOUNT, mSheetItems.get(2).type); - assertEquals("Incorrect account", CARL, mSheetItems.get(2).model.get(ACCOUNT)); - assertNull(mSheetItems.get(2).model.get(FAVICON_OR_FALLBACK)); - assertEquals("Incorrect type", ItemType.ACCOUNT, mSheetItems.get(3).type); - assertEquals("Incorrect account", BOB, mSheetItems.get(3).model.get(ACCOUNT)); - assertNull(mSheetItems.get(3).model.get(FAVICON_OR_FALLBACK)); - - verify(mMockIconBridge, times(3)) - .getLargeIconForUrl(eq(TEST_URL_1), eq(DESIRED_FAVICON_SIZE), any()); + public void testShowAccountAutoSignInHeader() { + mMediator.showAccounts(TEST_URL, TEST_URL_1, Arrays.asList(ANA), IDP_METADATA, + CLIENT_ID_METADATA, true /* isAutoSignIn */); + assertEquals(ItemType.HEADER, mSheetItems.get(0).type); + assertEquals(HeaderType.AUTO_SIGN_IN, mSheetItems.get(0).model.get(TYPE)); } @Test @@ -239,30 +191,6 @@ } @Test - public void testFetchFaviconUpdatesModel() { - mMediator.showAccounts(TEST_URL, TEST_URL_2, Collections.singletonList(CARL), IDP_METADATA, - CLIENT_ID_METADATA, false); - assertEquals("Incorrect item sheet count", 3, - mSheetItems.size()); // Header + Account + Continue Button - assertEquals("Incorrect type", ItemType.ACCOUNT, mSheetItems.get(1).type); - assertEquals("Incorrect account", CARL, mSheetItems.get(1).model.get(ACCOUNT)); - assertNull(mSheetItems.get(1).model.get(FAVICON_OR_FALLBACK)); - - verify(mMockIconBridge) - .getLargeIconForUrl(eq(TEST_URL_2), eq(DESIRED_FAVICON_SIZE), - mCallbackArgumentCaptor.capture()); - LargeIconBridge.LargeIconCallback callback = mCallbackArgumentCaptor.getValue(); - Bitmap bitmap = Bitmap.createBitmap( - DESIRED_FAVICON_SIZE, DESIRED_FAVICON_SIZE, Bitmap.Config.ARGB_8888); - callback.onLargeIconAvailable(bitmap, 333, true, IconType.FAVICON); - FaviconOrFallback iconData = mSheetItems.get(1).model.get(FAVICON_OR_FALLBACK); - assertEquals("incorrect favicon bitmap", bitmap, iconData.mIcon); - assertEquals("incorrect favicon url", TEST_URL_2, iconData.mUrl); - assertEquals("incorrect favicon size", DESIRED_FAVICON_SIZE, iconData.mIconSize); - assertEquals("incorrect favicon fallback color", 333, iconData.mFallbackColor); - } - - @Test public void testFetchAvatarUpdatesModel() { mMediator.showAccounts(TEST_URL, TEST_URL_1, Collections.singletonList(CARL), IDP_METADATA, CLIENT_ID_METADATA, false); @@ -305,7 +233,6 @@ mSheetItems.size()); // Header + Account + Continue Button assertEquals("Incorrect item type", ItemType.ACCOUNT, mSheetItems.get(1).type); assertEquals("Incorrect account", ANA, mSheetItems.get(1).model.get(ACCOUNT)); - assertNull(mSheetItems.get(1).model.get(FAVICON_OR_FALLBACK)); // Showing the sheet a second time should replace all changed accounts. mMediator.showAccounts(TEST_URL, TEST_URL_1, Collections.singletonList(BOB), IDP_METADATA, @@ -314,7 +241,6 @@ mSheetItems.size()); // Header + Account + Continue Button assertEquals("Incorrect item type", ItemType.ACCOUNT, mSheetItems.get(1).type); assertEquals("Incorrect account", BOB, mSheetItems.get(1).model.get(ACCOUNT)); - assertNull(mSheetItems.get(1).model.get(FAVICON_OR_FALLBACK)); } @Test @@ -496,6 +422,8 @@ @Test public void testShowVerifySheet() { when(mMockBottomSheetController.requestShowContent(any(), anyBoolean())).thenReturn(true); + mMediator.showAccounts(TEST_URL, TEST_URL_2, Arrays.asList(NEW_USER), IDP_METADATA, + CLIENT_ID_METADATA, false); mMediator.showVerifySheet(ANA); assertEquals(2, mSheetItems.size());
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionCoordinator.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionCoordinator.java index c0b46386..97bd4421 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionCoordinator.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionCoordinator.java
@@ -21,7 +21,6 @@ import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; import org.chromium.components.browser_ui.util.ConversionUtils; import org.chromium.components.browser_ui.util.GlobalDiscardableReferencePool; -import org.chromium.components.favicon.LargeIconBridge; import org.chromium.components.image_fetcher.ImageFetcher; import org.chromium.components.image_fetcher.ImageFetcherConfig; import org.chromium.components.image_fetcher.ImageFetcherFactory; @@ -68,13 +67,10 @@ GlobalDiscardableReferencePool.getReferencePool(), MAX_IMAGE_CACHE_SIZE); @Px - int avatar_size = - context.getResources().getDimensionPixelSize(R.dimen.list_item_start_icon_width); - @Px - int idp_icon_size = Math.round(avatar_size * 0.4f); + int avatarSize = context.getResources().getDimensionPixelSize( + R.dimen.account_selection_account_avatar_size); mMediator = new AccountSelectionMediator(delegate, sheetItems, mBottomSheetController, - mBottomSheetContent, imageFetcher, avatar_size, new LargeIconBridge(profile), - idp_icon_size); + mBottomSheetContent, imageFetcher, avatarSize); } static View setupContentView(Context context, ModelList sheetItems) {
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java index bcd4b8c..bfb091b 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionMediator.java
@@ -23,8 +23,6 @@ import org.chromium.components.browser_ui.bottomsheet.BottomSheetController.StateChangeReason; import org.chromium.components.browser_ui.bottomsheet.BottomSheetObserver; import org.chromium.components.browser_ui.bottomsheet.EmptyBottomSheetObserver; -import org.chromium.components.favicon.LargeIconBridge; -import org.chromium.components.favicon.LargeIconBridge.LargeIconCallback; import org.chromium.components.image_fetcher.ImageFetcher; import org.chromium.components.url_formatter.SchemeDisplay; import org.chromium.components.url_formatter.UrlFormatter; @@ -45,9 +43,7 @@ private final AccountSelectionComponent.Delegate mDelegate; private final ModelList mSheetItems; private final ImageFetcher mImageFetcher; - private final LargeIconBridge mLargeIconBridge; private final @Px int mDesiredAvatarSize; - private final @Px int mDesiredIconSize; private final BottomSheetController mBottomSheetController; private final AccountSelectionBottomSheetContent mBottomSheetContent; @@ -71,15 +67,13 @@ AccountSelectionMediator(AccountSelectionComponent.Delegate delegate, ModelList sheetItems, BottomSheetController bottomSheetController, AccountSelectionBottomSheetContent bottomSheetContent, ImageFetcher imageFetcher, - @Px int desiredAvatarSize, LargeIconBridge largeIconBridge, @Px int desiredIconSize) { + @Px int desiredAvatarSize) { assert delegate != null; mVisible = false; mDelegate = delegate; mSheetItems = sheetItems; mImageFetcher = imageFetcher; mDesiredAvatarSize = desiredAvatarSize; - mLargeIconBridge = largeIconBridge; - mDesiredIconSize = desiredIconSize; mBottomSheetController = bottomSheetController; mBottomSheetContent = bottomSheetContent; @@ -110,20 +104,9 @@ } // This method should not be used when the VERIFY header is needed. - private void addHeader(GURL rpUrl, GURL idpUrl, List<Account> accounts) { - boolean useSignInHeader = false; - for (Account account : accounts) { - if (!account.isSignIn()) continue; - useSignInHeader = true; - break; - } - HeaderType headerType; - if (useSignInHeader) { - headerType = HeaderType.SIGN_IN; - } else { - headerType = - accounts.size() == 1 ? HeaderType.SINGLE_ACCOUNT : HeaderType.MULTIPLE_ACCOUNT; - } + private void addHeader( + GURL rpUrl, GURL idpUrl, IdentityProviderMetadata idpMetadata, boolean isAutoSignIn) { + HeaderType headerType = isAutoSignIn ? HeaderType.AUTO_SIGN_IN : HeaderType.SIGN_IN; String formattedRpUrl = UrlFormatter.formatUrlForSecurityDisplay(rpUrl, SchemeDisplay.OMIT_HTTP_AND_HTTPS); String formattedIdpUrl = @@ -137,6 +120,7 @@ // allowed with WebID. mSheetItems.add(new ListItem(ItemType.HEADER, new PropertyModel.Builder(HeaderProperties.ALL_KEYS) + .with(HeaderProperties.IDP_BRAND_ICON, idpMetadata.getBrandIcon()) .with(HeaderProperties.CLOSE_ON_CLICK_LISTENER, closeOnClickRunnable) .with(HeaderProperties.FORMATTED_IDP_URL, formattedIdpUrl) .with(HeaderProperties.FORMATTED_RP_URL, formattedRpUrl) @@ -148,7 +132,6 @@ for (Account account : accounts) { final PropertyModel model = createAccountItem(account, areAccountsClickable); mSheetItems.add(new ListItem(ItemType.ACCOUNT, model)); - requestIconOrFallbackImage(model, idpUrl); requestAvatarImage(model); } } @@ -180,6 +163,7 @@ mSheetItems.add(new ListItem(ItemType.HEADER, new PropertyModel.Builder(HeaderProperties.ALL_KEYS) .with(HeaderProperties.CLOSE_ON_CLICK_LISTENER, closeOnClickRunnable) + .with(HeaderProperties.IDP_BRAND_ICON, mIdpMetadata.getBrandIcon()) .with(HeaderProperties.TYPE, HeaderType.VERIFY) .build())); @@ -215,7 +199,7 @@ accounts = Arrays.asList(selectedAccount); } - addHeader(rpUrl, idpUrl, accounts); + addHeader(rpUrl, idpUrl, idpMetadata, isAutoSignIn); addAccounts(idpUrl, accounts, /*areAccountsClickable=*/mSelectedAccount == null); if (isAutoSignIn) { @@ -276,16 +260,6 @@ } } - private void requestIconOrFallbackImage(PropertyModel accountModel, GURL idpUrl) { - Account account = accountModel.get(AccountProperties.ACCOUNT); - final LargeIconCallback setIcon = (icon, fallbackColor, hasDefaultColor, type) -> { - accountModel.set(AccountProperties.FAVICON_OR_FALLBACK, - new AccountProperties.FaviconOrFallback( - idpUrl, icon, fallbackColor, mDesiredIconSize)); - }; - mLargeIconBridge.getLargeIconForUrl(idpUrl, mDesiredIconSize, setIcon); - } - boolean isVisible() { return mVisible; }
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionProperties.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionProperties.java index b382188..9af06b8 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionProperties.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionProperties.java
@@ -15,7 +15,6 @@ import org.chromium.ui.modelutil.PropertyKey; import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey; import org.chromium.ui.modelutil.PropertyModel.WritableObjectPropertyKey; -import org.chromium.url.GURL; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -41,32 +40,14 @@ } } - static class FaviconOrFallback { - final GURL mUrl; - final @Nullable Bitmap mIcon; - final int mFallbackColor; - final int mIconSize; - - FaviconOrFallback( - GURL originUrl, @Nullable Bitmap icon, int fallbackColor, int iconSize) { - mUrl = originUrl; - mIcon = icon; - mFallbackColor = fallbackColor; - mIconSize = iconSize; - } - } - static final WritableObjectPropertyKey<Avatar> AVATAR = new WritableObjectPropertyKey<>("avatar"); - static final WritableObjectPropertyKey<FaviconOrFallback> FAVICON_OR_FALLBACK = - new WritableObjectPropertyKey<>("favicon"); static final ReadableObjectPropertyKey<Account> ACCOUNT = new ReadableObjectPropertyKey<>("account"); static final ReadableObjectPropertyKey<Callback<Account>> ON_CLICK_LISTENER = new ReadableObjectPropertyKey<>("on_click_listener"); - static final PropertyKey[] ALL_KEYS = { - AVATAR, FAVICON_OR_FALLBACK, ACCOUNT, ON_CLICK_LISTENER}; + static final PropertyKey[] ALL_KEYS = {AVATAR, ACCOUNT, ON_CLICK_LISTENER}; private AccountProperties() {} } @@ -76,18 +57,20 @@ * sheet. */ static class HeaderProperties { - public enum HeaderType { SINGLE_ACCOUNT, MULTIPLE_ACCOUNT, SIGN_IN, VERIFY } + public enum HeaderType { AUTO_SIGN_IN, SIGN_IN, VERIFY } static final ReadableObjectPropertyKey<Runnable> CLOSE_ON_CLICK_LISTENER = new ReadableObjectPropertyKey<>("close_on_click_listener"); static final ReadableObjectPropertyKey<String> FORMATTED_IDP_URL = new ReadableObjectPropertyKey<>("formatted_idp_url"); static final ReadableObjectPropertyKey<String> FORMATTED_RP_URL = new ReadableObjectPropertyKey<>("formatted_rp_url"); + static final ReadableObjectPropertyKey<Bitmap> IDP_BRAND_ICON = + new ReadableObjectPropertyKey<>("brand_icon"); static final ReadableObjectPropertyKey<HeaderType> TYPE = new ReadableObjectPropertyKey<>("type"); static final PropertyKey[] ALL_KEYS = { - CLOSE_ON_CLICK_LISTENER, FORMATTED_IDP_URL, FORMATTED_RP_URL, TYPE}; + CLOSE_ON_CLICK_LISTENER, FORMATTED_IDP_URL, FORMATTED_RP_URL, IDP_BRAND_ICON, TYPE}; private HeaderProperties() {} }
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java index 03a113b..3a9ad05 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewBinder.java
@@ -8,12 +8,7 @@ import android.content.res.ColorStateList; import android.content.res.Resources; import android.graphics.Bitmap; -import android.graphics.Canvas; import android.graphics.Color; -import android.graphics.Paint; -import android.graphics.PorterDuff; -import android.graphics.PorterDuffXfermode; -import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.text.SpannableString; import android.text.TextUtils; @@ -39,7 +34,6 @@ import org.chromium.chrome.browser.ui.android.webid.AccountSelectionProperties.HeaderProperties; import org.chromium.chrome.browser.ui.android.webid.data.Account; import org.chromium.chrome.browser.ui.android.webid.data.IdentityProviderMetadata; -import org.chromium.chrome.browser.ui.favicon.FaviconUtils; import org.chromium.components.browser_ui.util.AvatarGenerator; import org.chromium.components.browser_ui.widget.RoundedIconGenerator; import org.chromium.ui.modelutil.PropertyKey; @@ -74,16 +68,29 @@ */ static void bindAccountView(PropertyModel model, View view, PropertyKey key) { Account account = model.get(AccountProperties.ACCOUNT); - if (key == AccountProperties.AVATAR || key == AccountProperties.FAVICON_OR_FALLBACK) { + if (key == AccountProperties.AVATAR) { AccountProperties.Avatar avatarData = model.get(AccountProperties.AVATAR); - AccountProperties.FaviconOrFallback faviconData = - model.get(AccountProperties.FAVICON_OR_FALLBACK); - // Wait for both avatar and favicon to be available before drawing them to avoid - // unnecessary flashing. - if (avatarData == null || faviconData == null) return; - Drawable badgedAvatar = overlayIdpFaviconOnAvatar(view, avatarData, faviconData); + int avatarSize = avatarData.mAvatarSize; + Bitmap avatar = avatarData.mAvatar; + + Resources resources = view.getContext().getResources(); + + // Prepare avatar or its fallback monogram. + if (avatar == null) { + int avatarMonogramTextSize = view.getResources().getDimensionPixelSize( + R.dimen.account_selection_account_avatar_monogram_text_size); + // TODO(crbug.com/1295017): Consult UI team to determine the background color we + // need to use here. + RoundedIconGenerator roundedIconGenerator = + new RoundedIconGenerator(resources, avatarSize /* iconWidthDp */, + avatarSize /* iconHeightDp */, avatarSize / 2 /* cornerRadiusDp */, + Color.GRAY /* backgroundColor */, avatarMonogramTextSize); + avatar = roundedIconGenerator.generateIconForText(avatarData.mName); + } + Drawable croppedAvatar = AvatarGenerator.makeRoundAvatar(resources, avatar, avatarSize); + ImageView avatarView = view.findViewById(R.id.start_icon); - avatarView.setImageDrawable(badgedAvatar); + avatarView.setImageDrawable(croppedAvatar); } else if (key == AccountProperties.ON_CLICK_LISTENER) { view.setOnClickListener(clickedView -> { model.get(AccountProperties.ON_CLICK_LISTENER).onResult(account); @@ -98,78 +105,6 @@ } } - /** - * Creates a drawable that is a combination of the User's avatar and the Identity Provider's - * (IdP) favicon. The final drawable is a square with avatarData.mAvatarSize dimension that - * contains two rounded images overlayed on top of each other like so: - * +------------+ - * | | - * | Avatar | - * | +----+ - * | |Favi| - * | |con | - * +-------+----+ - * - * @param view The view to be bound. - * @param avatarData The data for the avatar. If the bitmap is null then we generate a - * placeholder monogram avatar using the name. - * @param faviconData The data for the favicon including its bitmap and size. - */ - static Drawable overlayIdpFaviconOnAvatar(View view, AccountProperties.Avatar avatarData, - AccountProperties.FaviconOrFallback faviconData) { - int avatarSize = avatarData.mAvatarSize; - int badgeSize = faviconData.mIconSize; - int frameSize = avatarSize; - // Avatar touches the top/left sides of frame, badge touches bottom/right sides of the - // frame. - int avatarX = 0; - int avatarY = 0; - int badgeX = frameSize - badgeSize; - int badgeY = frameSize - badgeSize; - - RoundedIconGenerator roundedIconGenerator = - FaviconUtils.createCircularIconGenerator(view.getResources()); - - // Prepare avatar or its fallback monogram. - Bitmap avatar = avatarData.mAvatar; - if (avatar == null) { - // TODO(majidvp): Consult UI team to determine the background color we need to use here. - roundedIconGenerator.setBackgroundColor(Color.GRAY); - avatar = roundedIconGenerator.generateIconForText(avatarData.mName); - } - Drawable croppedAvatar = - AvatarGenerator.makeRoundAvatar(view.getResources(), avatar, avatarSize); - Bitmap badgedAvatar = Bitmap.createBitmap(avatarSize, avatarSize, Bitmap.Config.ARGB_8888); - Canvas canvas = new Canvas(badgedAvatar); - - // Draw the avatar. - croppedAvatar.setBounds(avatarX, avatarY, avatarSize, avatarSize); - croppedAvatar.draw(canvas); - - // Cut a transparent hole through the avatar image. This will serve as a border to the badge - // being overlaid. - int badgeRadius = badgeSize / 2; - int badgeCenterX = badgeX + badgeRadius; - int badgeCenterY = badgeY + badgeRadius; - int badgeBorderSize = view.getResources().getDimensionPixelSize( - R.dimen.account_selection_favicon_border_size); - - Paint paint = new Paint(); - paint.setAntiAlias(true); - paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); - canvas.drawCircle(badgeCenterX, badgeCenterY, badgeRadius + badgeBorderSize, paint); - - // Prepare the IDP favicon as the badge. - Drawable favicon = FaviconUtils.getIconDrawableWithoutFilter(faviconData.mIcon, - faviconData.mUrl, faviconData.mFallbackColor, roundedIconGenerator, - view.getResources(), badgeSize); - - // Draw the badge. - favicon.setBounds(badgeX, badgeY, badgeX + badgeSize, badgeY + badgeSize); - favicon.draw(canvas); - return new BitmapDrawable(view.getResources(), badgedAvatar); - } - static void openTab(String url) { TabCreator tabCreator = (sTabCreatorForTesting == null) ? new TabDelegate(/* incognito */ false) @@ -313,34 +248,25 @@ * @param key The key of the property to be bound. */ static void bindHeaderView(PropertyModel model, View view, PropertyKey key) { - if (key == HeaderProperties.FORMATTED_RP_URL || key == HeaderProperties.TYPE) { + if (key == HeaderProperties.FORMATTED_RP_URL || key == HeaderProperties.FORMATTED_IDP_URL + || key == HeaderProperties.TYPE) { TextView headerTitleText = view.findViewById(R.id.header_title); - @StringRes - int titleStringId = R.string.account_selection_sheet_title_single; - switch (model.get(HeaderProperties.TYPE)) { - case SINGLE_ACCOUNT: - titleStringId = R.string.account_selection_sheet_title_single; - break; - case MULTIPLE_ACCOUNT: - titleStringId = R.string.account_selection_sheet_title; - break; - case SIGN_IN: - titleStringId = R.string.sign_in_sheet_title; - break; - case VERIFY: - titleStringId = R.string.verify_sheet_title; - break; - } - - String title = String.format(view.getContext().getString(titleStringId), - model.get(HeaderProperties.FORMATTED_RP_URL)); - headerTitleText.setText(title); - } else if (key == HeaderProperties.FORMATTED_IDP_URL) { - String subheadingText = String.format( - view.getContext().getString(R.string.account_selection_sheet_idp_subheader), + String title = computeHeaderTitle(view.getResources(), model.get(HeaderProperties.TYPE), + model.get(HeaderProperties.FORMATTED_RP_URL), model.get(HeaderProperties.FORMATTED_IDP_URL)); - TextView headerIdpUrlText = view.findViewById(R.id.header_idp_url); - headerIdpUrlText.setText(subheadingText); + headerTitleText.setText(title); + } else if (key == HeaderProperties.IDP_BRAND_ICON) { + Bitmap brandIcon = model.get(HeaderProperties.IDP_BRAND_ICON); + if (brandIcon != null) { + Resources resources = view.getResources(); + int iconSize = resources.getDimensionPixelSize( + R.dimen.account_selection_continue_icon_size); + Drawable croppedBrandIcon = + AvatarGenerator.makeRoundAvatar(resources, brandIcon, iconSize); + ImageView headerIconView = (ImageView) view.findViewById(R.id.header_idp_icon); + headerIconView.setImageDrawable(croppedBrandIcon); + headerIconView.setVisibility(View.VISIBLE); + } } else if (key == HeaderProperties.CLOSE_ON_CLICK_LISTENER) { final Runnable closeOnClickRunnable = (Runnable) model.get(HeaderProperties.CLOSE_ON_CLICK_LISTENER); @@ -352,5 +278,17 @@ } } + private static String computeHeaderTitle( + Resources resources, HeaderProperties.HeaderType type, String rpUrl, String idpUrl) { + if (type == HeaderProperties.HeaderType.VERIFY) { + return resources.getString(R.string.verify_sheet_title); + } + @StringRes + int titleStringId = (type == HeaderProperties.HeaderType.AUTO_SIGN_IN) + ? R.string.account_selection_sheet_title_auto + : R.string.account_selection_sheet_title_explicit; + return String.format(resources.getString(titleStringId), rpUrl, idpUrl); + } + private AccountSelectionViewBinder() {} }
diff --git a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java index 5f3c146..96f6b1e 100644 --- a/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java +++ b/chrome/browser/ui/android/webid/internal/java/src/org/chromium/chrome/browser/ui/android/webid/AccountSelectionViewTest.java
@@ -98,38 +98,39 @@ @Test @MediumTest - public void testSingleAccountTitleDisplayed() { + public void testSignInTitleDisplayed() { TestThreadUtils.runOnUiThreadBlocking(() -> { mSheetItems.add(new MVCListAdapter.ListItem(AccountSelectionProperties.ItemType.HEADER, new PropertyModel.Builder(HeaderProperties.ALL_KEYS) - .with(HeaderProperties.TYPE, HeaderType.SINGLE_ACCOUNT) + .with(HeaderProperties.TYPE, HeaderType.SIGN_IN) .with(HeaderProperties.FORMATTED_RP_URL, "www.example.org") + .with(HeaderProperties.FORMATTED_IDP_URL, "www.idp.org") .build())); }); pollUiThread(() -> mContentView.getVisibility() == View.VISIBLE); TextView title = mContentView.findViewById(R.id.header_title); assertEquals("Incorrect title", - mActivity.getString( - R.string.account_selection_sheet_title_single, "www.example.org"), + mActivity.getString(R.string.account_selection_sheet_title_explicit, + "www.example.org", "www.idp.org"), title.getText()); } @Test @MediumTest - public void testMultiAccountTitleDisplayed() { + public void testVerifyingTitleDisplayed() { TestThreadUtils.runOnUiThreadBlocking(() -> { mSheetItems.add(new MVCListAdapter.ListItem(AccountSelectionProperties.ItemType.HEADER, new PropertyModel.Builder(HeaderProperties.ALL_KEYS) - .with(HeaderProperties.TYPE, HeaderType.MULTIPLE_ACCOUNT) + .with(HeaderProperties.TYPE, HeaderType.VERIFY) .with(HeaderProperties.FORMATTED_RP_URL, "www.example.org") + .with(HeaderProperties.FORMATTED_IDP_URL, "www.idp.org") .build())); }); pollUiThread(() -> mContentView.getVisibility() == View.VISIBLE); TextView title = mContentView.findViewById(R.id.header_title); - assertEquals("Incorrect title", - mActivity.getString(R.string.account_selection_sheet_title, "www.example.org"), + assertEquals("Incorrect title", mActivity.getString(R.string.verify_sheet_title), title.getText()); } @@ -217,15 +218,17 @@ TestThreadUtils.runOnUiThreadBlocking(() -> { mSheetItems.add(new MVCListAdapter.ListItem(AccountSelectionProperties.ItemType.HEADER, new PropertyModel.Builder(HeaderProperties.ALL_KEYS) - .with(HeaderProperties.TYPE, HeaderType.SIGN_IN) + .with(HeaderProperties.TYPE, HeaderType.AUTO_SIGN_IN) .with(HeaderProperties.FORMATTED_RP_URL, "www.example.org") + .with(HeaderProperties.FORMATTED_IDP_URL, "www.idp.org") .build())); }); pollUiThread(() -> mContentView.getVisibility() == View.VISIBLE); TextView title = mContentView.findViewById(R.id.header_title); assertEquals("Incorrect title", - mActivity.getString(R.string.sign_in_sheet_title, "www.example.org"), + mActivity.getString(R.string.account_selection_sheet_title_auto, "www.example.org", + "www.idp.org"), title.getText()); }
diff --git a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc index ff7618f..bd72eb1 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_list_prefs.cc
@@ -1531,19 +1531,6 @@ std::move(permission_state_dict)); } package_dict->SetKey(kPermissionStates, std::move(permissions_dict)); - } else if (package.permissions.has_value()) { - // Support deprecated format - for (const auto& permission : package.permissions.value()) { - base::DictionaryValue permission_state_dict; - permission_state_dict.SetBoolKey(kPermissionStateGranted, - permission.second); - // Assume deprecated format is not managed. - permission_state_dict.SetBoolKey(kPermissionStateManaged, false); - permissions_dict.SetKey( - base::NumberToString(static_cast<int64_t>(permission.first)), - std::move(permission_state_dict)); - } - package_dict->SetKey(kPermissionStates, std::move(permissions_dict)); } else { // Remove kPermissionStates from dict if there are no permissions. package_dict->RemoveKey(kPermissionStates);
diff --git a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc index 5bdbf79..d7bdbc1 100644 --- a/chrome/browser/ui/app_list/arc/arc_app_unittest.cc +++ b/chrome/browser/ui/app_list/arc/arc_app_unittest.cc
@@ -1161,7 +1161,7 @@ // TODO(crbug.com/1253250): Remove apps::mojom related code. apps_util::IncrementingIconKeyFactory icon_key_factory; std::vector<apps::mojom::AppPtr> mojom_apps; - std::vector<std::unique_ptr<apps::App>> apps; + std::vector<apps::AppPtr> apps; for (const auto& app_id : app_ids) { apps::mojom::AppPtr mojom_app = apps::mojom::App::New(); mojom_app->app_type = apps::mojom::AppType::kArc;
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc index 7f34347d..17e86728f 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.cc
@@ -36,12 +36,14 @@ Profile* profile, AppListControllerDelegate* list_controller, bool is_recommendation, - const std::u16string& query) + const std::u16string& query, + const std::string& details) : data_(std::move(data)), profile_(profile), list_controller_(list_controller) { const auto title = base::UTF8ToUTF16(data_->short_label); SetTitle(title); + SetDetails(base::UTF8ToUTF16(details)); if (!query.empty()) SetTitleTags(CalculateTags(query, title)); set_id(kAppShortcutSearchPrefix + GetAppId() + "/" + data_->shortcut_id);
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h index 9987af8..a0f0e06 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h +++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcut_search_result.h
@@ -34,7 +34,8 @@ Profile* profile, AppListControllerDelegate* list_controller, bool is_recommendation, - const std::u16string& query); + const std::u16string& query, + const std::string& details); ArcAppShortcutSearchResult(const ArcAppShortcutSearchResult&) = delete; ArcAppShortcutSearchResult& operator=(const ArcAppShortcutSearchResult&) =
diff --git a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc index 20b18de..effbfee 100644 --- a/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc +++ b/chrome/browser/ui/app_list/search/arc/arc_app_shortcuts_search_provider.cc
@@ -81,7 +81,7 @@ continue; auto result = std::make_unique<ArcAppShortcutSearchResult>( std::move(item), profile_, list_controller_, true /*is_recommendation*/, - std::u16string() /*query*/); + std::u16string() /*query*/, app_info->name); if (!app_info->install_time.is_null() || !app_info->last_launch_time.is_null()) { @@ -113,7 +113,7 @@ continue; search_results.emplace_back(std::make_unique<ArcAppShortcutSearchResult>( std::move(item), profile_, list_controller_, - false /*is_recommendation*/, last_query_)); + false /*is_recommendation*/, last_query_, app_info->name)); } SwapResults(&search_results); }
diff --git a/chrome/browser/ui/app_list/search/files/file_search_provider.cc b/chrome/browser/ui/app_list/search/files/file_search_provider.cc index 51409f8..b2687ec 100644 --- a/chrome/browser/ui/app_list/search/files/file_search_provider.cc +++ b/chrome/browser/ui/app_list/search/files/file_search_provider.cc
@@ -158,16 +158,17 @@ const double relevance) { const auto type = path.is_directory ? FileResult::Type::kDirectory : FileResult::Type::kFile; - // Use the display name of the Files app as the details text. - std::u16string details_text = base::CollapseWhitespace( - l10n_util::GetStringUTF16(IDS_FILEMANAGER_APP_NAME), true); - base::i18n::SanitizeUserSuppliedString(&details_text); + // Use the parent directory name as details text. Take care to remove newlines + // and handle RTL as this is displayed directly. + std::u16string parent_dir_name = base::CollapseWhitespace( + path.path.DirName().BaseName().LossyDisplayName(), true); + base::i18n::SanitizeUserSuppliedString(&parent_dir_name); - auto result = - std::make_unique<FileResult>(kFileSearchSchema, path.path, details_text, - ash::AppListSearchResultType::kFileSearch, - ash::SearchResultDisplayType::kList, - relevance, last_query_, type, profile_); + auto result = std::make_unique<FileResult>( + kFileSearchSchema, path.path, parent_dir_name, + ash::AppListSearchResultType::kFileSearch, + ash::SearchResultDisplayType::kList, relevance, last_query_, type, + profile_); result->RequestThumbnail(&thumbnail_loader_); return result; }
diff --git a/chrome/browser/ui/app_list/search/files/zero_state_drive_provider.cc b/chrome/browser/ui/app_list/search/files/zero_state_drive_provider.cc index a5991fe..dab5d46 100644 --- a/chrome/browser/ui/app_list/search/files/zero_state_drive_provider.cc +++ b/chrome/browser/ui/app_list/search/files/zero_state_drive_provider.cc
@@ -302,7 +302,7 @@ const float relevance) { const auto reparented_path = ReparentToDriveMount(filepath, drive_service_); auto result = std::make_unique<FileResult>( - kSchema, reparented_path, GetJustificationString(reparented_path), + kSchema, reparented_path, std::u16string(), ash::AppListSearchResultType::kZeroStateDrive, GetDisplayType(), relevance, std::u16string(), FileResult::Type::kFile, profile_); // If it exists, override the details text with the prediction reason in the
diff --git a/chrome/browser/ui/app_list/search/files/zero_state_file_provider.cc b/chrome/browser/ui/app_list/search/files/zero_state_file_provider.cc index 8335ff0..5f9f4a3 100644 --- a/chrome/browser/ui/app_list/search/files/zero_state_file_provider.cc +++ b/chrome/browser/ui/app_list/search/files/zero_state_file_provider.cc
@@ -145,7 +145,7 @@ const auto& filepath = valid_results[i].first; double score = valid_results[i].second; auto result = std::make_unique<FileResult>( - kSchema, filepath, GetJustificationString(filepath), + kSchema, filepath, std::u16string(), ash::AppListSearchResultType::kZeroStateFile, GetDisplayType(), score, std::u16string(), FileResult::Type::kFile, profile_); // TODO(crbug.com/1258415): Only generate thumbnails if the old launcher is
diff --git a/chrome/browser/ui/ash/arc_open_url_delegate_impl.cc b/chrome/browser/ui/ash/arc_open_url_delegate_impl.cc index f50f1aa..1751f76 100644 --- a/chrome/browser/ui/ash/arc_open_url_delegate_impl.cc +++ b/chrome/browser/ui/ash/arc_open_url_delegate_impl.cc
@@ -10,6 +10,7 @@ #include "ash/components/arc/mojom/intent_helper.mojom.h" #include "base/check.h" +#include "base/containers/fixed_flat_map.h" #include "base/files/safe_base_name.h" #include "base/notreached.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" @@ -54,65 +55,71 @@ ArcOpenUrlDelegateImpl* g_instance = nullptr; -constexpr std::pair<arc::mojom::ChromePage, const char*> kOSSettingsMapping[] = - {{ChromePage::ACCOUNTS, - chromeos::settings::mojom::kManageOtherPeopleSubpagePathV2}, - {ChromePage::BLUETOOTH, - chromeos::settings::mojom::kBluetoothDevicesSubpagePath}, - {ChromePage::BLUETOOTHDEVICES, - chromeos::settings::mojom::kBluetoothDevicesSubpagePath}, - {ChromePage::CHANGEPICTURE, - chromeos::settings::mojom::kChangePictureSubpagePath}, - {ChromePage::CUPSPRINTERS, - chromeos::settings::mojom::kPrintingDetailsSubpagePath}, - {ChromePage::DATETIME, chromeos::settings::mojom::kDateAndTimeSectionPath}, - {ChromePage::DISPLAY, chromeos::settings::mojom::kDisplaySubpagePath}, - {ChromePage::HELP, chromeos::settings::mojom::kAboutChromeOsSectionPath}, - {ChromePage::KEYBOARDOVERLAY, - chromeos::settings::mojom::kKeyboardSubpagePath}, - {ChromePage::OSLANGUAGESINPUT, - chromeos::settings::mojom::kInputSubpagePath}, - {ChromePage::OSLANGUAGESLANGUAGES, - chromeos::settings::mojom::kLanguagesSubpagePath}, - {ChromePage::LOCKSCREEN, - chromeos::settings::mojom::kSecurityAndSignInSubpagePathV2}, - {ChromePage::MAIN, ""}, - {ChromePage::MANAGEACCESSIBILITY, - chromeos::settings::mojom::kManageAccessibilitySubpagePath}, - {ChromePage::MANAGEACCESSIBILITYTTS, - chromeos::settings::mojom::kTextToSpeechSubpagePath}, - {ChromePage::MULTIDEVICE, - chromeos::settings::mojom::kMultiDeviceSectionPath}, - {ChromePage::NETWORKSTYPEVPN, - chromeos::settings::mojom::kVpnDetailsSubpagePath}, - {ChromePage::POINTEROVERLAY, - chromeos::settings::mojom::kPointersSubpagePath}, - {ChromePage::POWER, chromeos::settings::mojom::kPowerSubpagePath}, - {ChromePage::SMARTPRIVACY, - chromeos::settings::mojom::kSmartPrivacySubpagePath}, - {ChromePage::STORAGE, chromeos::settings::mojom::kStorageSubpagePath}, - {ChromePage::WIFI, chromeos::settings::mojom::kWifiNetworksSubpagePath}}; +constexpr auto kOSSettingsMap = + base::MakeFixedFlatMap<ChromePage, const char*>({ + {ChromePage::ACCOUNTS, + chromeos::settings::mojom::kManageOtherPeopleSubpagePathV2}, + {ChromePage::BLUETOOTH, + chromeos::settings::mojom::kBluetoothDevicesSubpagePath}, + {ChromePage::BLUETOOTHDEVICES, + chromeos::settings::mojom::kBluetoothDevicesSubpagePath}, + {ChromePage::CHANGEPICTURE, + chromeos::settings::mojom::kChangePictureSubpagePath}, + {ChromePage::CUPSPRINTERS, + chromeos::settings::mojom::kPrintingDetailsSubpagePath}, + {ChromePage::DATETIME, + chromeos::settings::mojom::kDateAndTimeSectionPath}, + {ChromePage::DISPLAY, chromeos::settings::mojom::kDisplaySubpagePath}, + {ChromePage::HELP, + chromeos::settings::mojom::kAboutChromeOsSectionPath}, + {ChromePage::KEYBOARDOVERLAY, + chromeos::settings::mojom::kKeyboardSubpagePath}, + {ChromePage::LOCKSCREEN, + chromeos::settings::mojom::kSecurityAndSignInSubpagePathV2}, + {ChromePage::MAIN, ""}, + {ChromePage::MANAGEACCESSIBILITY, + chromeos::settings::mojom::kManageAccessibilitySubpagePath}, + {ChromePage::MANAGEACCESSIBILITYTTS, + chromeos::settings::mojom::kTextToSpeechSubpagePath}, + {ChromePage::MULTIDEVICE, + chromeos::settings::mojom::kMultiDeviceSectionPath}, + {ChromePage::NETWORKSTYPEVPN, + chromeos::settings::mojom::kVpnDetailsSubpagePath}, + {ChromePage::OSLANGUAGESINPUT, + chromeos::settings::mojom::kInputSubpagePath}, + {ChromePage::OSLANGUAGESLANGUAGES, + chromeos::settings::mojom::kLanguagesSubpagePath}, + {ChromePage::POINTEROVERLAY, + chromeos::settings::mojom::kPointersSubpagePath}, + {ChromePage::POWER, chromeos::settings::mojom::kPowerSubpagePath}, + {ChromePage::SMARTPRIVACY, + chromeos::settings::mojom::kSmartPrivacySubpagePath}, + {ChromePage::STORAGE, chromeos::settings::mojom::kStorageSubpagePath}, + {ChromePage::WIFI, chromeos::settings::mojom::kWifiNetworksSubpagePath}, + }); -constexpr std::pair<arc::mojom::ChromePage, const char*> - kBrowserSettingsMapping[] = { +constexpr auto kBrowserSettingsMap = + base::MakeFixedFlatMap<ChromePage, const char*>({ {ChromePage::APPEARANCE, chrome::kAppearanceSubPage}, {ChromePage::AUTOFILL, chrome::kAutofillSubPage}, {ChromePage::CLEARBROWSERDATA, chrome::kClearBrowserDataSubPage}, {ChromePage::CLOUDPRINTERS, chrome::kCloudPrintersSubPage}, {ChromePage::DOWNLOADS, chrome::kDownloadsSubPage}, + {ChromePage::LANGUAGES, chrome::kLanguagesSubPage}, {ChromePage::ONSTARTUP, chrome::kOnStartupSubPage}, {ChromePage::PASSWORDS, chrome::kPasswordManagerSubPage}, {ChromePage::PRIVACY, chrome::kPrivacySubPage}, {ChromePage::RESET, chrome::kResetSubPage}, {ChromePage::SEARCH, chrome::kSearchSubPage}, {ChromePage::SYNCSETUP, chrome::kSyncSetupSubPage}, - {ChromePage::LANGUAGES, chrome::kLanguagesSubPage}, -}; + }); -constexpr std::pair<arc::mojom::ChromePage, const char*> kAboutPagesMapping[] = - {{ChromePage::ABOUTBLANK, url::kAboutBlankURL}, - {ChromePage::ABOUTDOWNLOADS, "chrome://downloads/"}, - {ChromePage::ABOUTHISTORY, "chrome://history/"}}; +constexpr auto kAboutPagesMap = + base::MakeFixedFlatMap<ChromePage, const char*>({ + {ChromePage::ABOUTBLANK, url::kAboutBlankURL}, + {ChromePage::ABOUTDOWNLOADS, "chrome://downloads/"}, + {ChromePage::ABOUTHISTORY, "chrome://history/"}, + }); // Converts the given ARC URL to an external file URL to read it via ARC content // file system when necessary. Otherwise, returns the given URL unchanged. @@ -167,13 +174,7 @@ } // namespace -ArcOpenUrlDelegateImpl::ArcOpenUrlDelegateImpl() - : os_settings_pages_(std::cbegin(kOSSettingsMapping), - std::cend(kOSSettingsMapping)), - browser_settings_pages_(std::cbegin(kBrowserSettingsMapping), - std::cend(kBrowserSettingsMapping)), - about_pages_(std::cbegin(kAboutPagesMapping), - std::cend(kAboutPagesMapping)) { +ArcOpenUrlDelegateImpl::ArcOpenUrlDelegateImpl() { arc::ArcIntentHelperBridge::SetOpenUrlDelegate(this); DCHECK(!g_instance); g_instance = this; @@ -314,22 +315,20 @@ } void ArcOpenUrlDelegateImpl::OpenChromePageFromArc(ChromePage page) { - auto it = os_settings_pages_.find(page); - if (it != os_settings_pages_.end()) { + if (auto* it = kOSSettingsMap.find(page); it != kOSSettingsMap.end()) { Profile* profile = ProfileManager::GetActiveUserProfile(); chrome::SettingsWindowManager::GetInstance()->ShowOSSettings(profile, it->second); return; } - it = browser_settings_pages_.find(page); - if (it != browser_settings_pages_.end()) { + if (auto* it = kBrowserSettingsMap.find(page); + it != kBrowserSettingsMap.end()) { OpenUrlFromArc(GURL(chrome::kChromeUISettingsURL).Resolve(it->second)); return; } - it = about_pages_.find(page); - if (it != about_pages_.end()) { + if (auto* it = kAboutPagesMap.find(page); it != kAboutPagesMap.end()) { OpenUrlFromArc(GURL(it->second)); return; }
diff --git a/chrome/browser/ui/ash/arc_open_url_delegate_impl.h b/chrome/browser/ui/ash/arc_open_url_delegate_impl.h index 603adc7..85ab57b 100644 --- a/chrome/browser/ui/ash/arc_open_url_delegate_impl.h +++ b/chrome/browser/ui/ash/arc_open_url_delegate_impl.h
@@ -5,10 +5,7 @@ #ifndef CHROME_BROWSER_UI_ASH_ARC_OPEN_URL_DELEGATE_IMPL_H_ #define CHROME_BROWSER_UI_ASH_ARC_OPEN_URL_DELEGATE_IMPL_H_ -#include <string> - #include "ash/components/arc/mojom/intent_helper.mojom.h" -#include "base/containers/flat_map.h" #include "components/arc/intent_helper/open_url_delegate.h" // Implements arc::OpenUrlDelegate to inject dependency. @@ -34,13 +31,6 @@ void OpenChromePageFromArc(arc::mojom::ChromePage page) override; void OpenAppWithIntent(const GURL& start_url, arc::mojom::LaunchIntentPtr intent) override; - - private: - // TODO(hidehiko): Move these out form members. - const base::flat_map<arc::mojom::ChromePage, std::string> os_settings_pages_; - const base::flat_map<arc::mojom::ChromePage, std::string> - browser_settings_pages_; - const base::flat_map<arc::mojom::ChromePage, std::string> about_pages_; }; #endif // CHROME_BROWSER_UI_ASH_ARC_OPEN_URL_DELEGATE_IMPL_H_
diff --git a/chrome/browser/ui/ash/ime_controller_client_impl_unittest.cc b/chrome/browser/ui/ash/ime_controller_client_impl_unittest.cc index a64c5f1..dd5382bc 100644 --- a/chrome/browser/ui/ash/ime_controller_client_impl_unittest.cc +++ b/chrome/browser/ui/ash/ime_controller_client_impl_unittest.cc
@@ -289,11 +289,8 @@ TEST_F(ImeControllerClientImplTest, MenuItemChanged) { ImeControllerClientImpl client(&input_method_manager_); client.Init(); - const bool is_selection_item = true; - InputMethodMenuItem item1("key1", "label1", is_selection_item, - true /* checked */); - InputMethodMenuItem item2("key2", "label2", is_selection_item, - false /* checked */); + InputMethodMenuItem item1("key1", "label1", true /* checked */); + InputMethodMenuItem item2("key2", "label2", false /* checked */); // Setting the list triggers the InputMethodMenuItemChanged event. InputMethodMenuManager::GetInstance()->SetCurrentInputMethodMenuItemList(
diff --git a/chrome/browser/ui/extensions/extension_site_access_combobox_model.cc b/chrome/browser/ui/extensions/extension_site_access_combobox_model.cc new file mode 100644 index 0000000..f632bc72 --- /dev/null +++ b/chrome/browser/ui/extensions/extension_site_access_combobox_model.cc
@@ -0,0 +1,116 @@ +// Copyright 2022 The Chromium 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/extensions/extension_site_access_combobox_model.h" + +#include "base/metrics/user_metrics.h" +#include "base/metrics/user_metrics_action.h" +#include "chrome/browser/extensions/scripting_permissions_modifier.h" +#include "chrome/browser/extensions/site_permissions_helper.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/grit/generated_resources.h" +#include "content/public/browser/web_contents.h" +#include "extensions/browser/extension_registry.h" +#include "extensions/common/extension.h" +#include "ui/base/l10n/l10n_util.h" + +ExtensionSiteAccessComboboxModel::ExtensionSiteAccessComboboxModel( + Browser* browser, + const extensions::Extension* extension) + : browser_(browser), extension_(extension) { + items_.push_back(extensions::SitePermissionsHelper::SiteAccess::kOnClick); + items_.push_back(extensions::SitePermissionsHelper::SiteAccess::kOnSite); + items_.push_back(extensions::SitePermissionsHelper::SiteAccess::kOnAllSites); +} + +ExtensionSiteAccessComboboxModel::~ExtensionSiteAccessComboboxModel() = default; + +void ExtensionSiteAccessComboboxModel::HandleSelection(int new_index) { + content::WebContents* web_contents = + browser_->tab_strip_model()->GetActiveWebContents(); + if (!web_contents || !ExtensionIsValid()) + return; + DCHECK_LT(static_cast<size_t>(new_index), items_.size()); + + LogSiteAccessAction(items_[new_index]); + + extensions::SitePermissionsHelper(browser_->profile()) + .UpdateSiteAccess(*extension_, web_contents, items_[new_index]); +} + +int ExtensionSiteAccessComboboxModel::GetCurrentSiteAccessIndex() const { + DCHECK(ExtensionIsValid()); + + content::WebContents* web_contents = + browser_->tab_strip_model()->GetActiveWebContents(); + DCHECK(web_contents); + + extensions::SitePermissionsHelper::SiteAccess current_access = + extensions::SitePermissionsHelper(browser_->profile()) + .GetCurrentSiteAccess(*extension_, web_contents); + auto item_it = std::find(items_.begin(), items_.end(), current_access); + DCHECK(item_it != items_.end()); + + return item_it - items_.begin(); +} + +int ExtensionSiteAccessComboboxModel::GetItemCount() const { + return items_.size(); +} + +std::u16string ExtensionSiteAccessComboboxModel::GetItemAt(int index) const { + int label_id = 0; + switch (items_[index]) { + case extensions::SitePermissionsHelper::SiteAccess::kOnClick: + label_id = IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_CLICK; + break; + case extensions::SitePermissionsHelper::SiteAccess::kOnSite: + label_id = IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_SITE; + break; + case extensions::SitePermissionsHelper::SiteAccess::kOnAllSites: + label_id = IDS_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX_RUN_ON_ALL_SITES; + break; + } + return l10n_util::GetStringUTF16(label_id); +} + +int ExtensionSiteAccessComboboxModel::GetDefaultIndex() const { + return GetCurrentSiteAccessIndex(); +} + +bool ExtensionSiteAccessComboboxModel::IsItemEnabledAt(int index) const { + content::WebContents* web_contents = + browser_->tab_strip_model()->GetActiveWebContents(); + if (!web_contents || !ExtensionIsValid()) + return false; + + return extensions::SitePermissionsHelper(browser_->profile()) + .CanSelectSiteAccess(*extension_, web_contents->GetLastCommittedURL(), + items_[index]); +} + +bool ExtensionSiteAccessComboboxModel::ExtensionIsValid() const { + return extensions::ExtensionRegistry::Get(browser_->profile()) + ->enabled_extensions() + .Contains(extension_->id()); +} + +void ExtensionSiteAccessComboboxModel::LogSiteAccessAction( + extensions::SitePermissionsHelper::SiteAccess site_access) const { + switch (site_access) { + case extensions::SitePermissionsHelper::SiteAccess::kOnClick: + base::RecordAction(base::UserMetricsAction( + "Extensions.Toolbar.SiteAccessCombobox.OnClickSelected")); + break; + case extensions::SitePermissionsHelper::SiteAccess::kOnSite: + base::RecordAction(base::UserMetricsAction( + "Extensions.Toolbar.SiteAccessCombobox.OnSiteSelected")); + break; + case extensions::SitePermissionsHelper::SiteAccess::kOnAllSites: + base::RecordAction(base::UserMetricsAction( + "Extensions.Toolbar.SiteAccessCombobox.OnAllSitesSelected")); + break; + } +}
diff --git a/chrome/browser/ui/extensions/extension_site_access_combobox_model.h b/chrome/browser/ui/extensions/extension_site_access_combobox_model.h new file mode 100644 index 0000000..9c652b9 --- /dev/null +++ b/chrome/browser/ui/extensions/extension_site_access_combobox_model.h
@@ -0,0 +1,61 @@ +// Copyright 2022 The Chromium 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_EXTENSIONS_EXTENSION_SITE_ACCESS_COMBOBOX_MODEL_H_ +#define CHROME_BROWSER_UI_EXTENSIONS_EXTENSION_SITE_ACCESS_COMBOBOX_MODEL_H_ + +#include <vector> + +#include "chrome/browser/extensions/site_permissions_helper.h" +#include "ui/base/models/combobox_model.h" + +class Browser; + +// The model for the site access combobox in the extensions menu. This manages +// the user's manipulation of the combobox and offers the data to show on it. +// Since this class doesn't own the extension, be sure to check for validity +// using ExtensionIsValid() before using those members. +class ExtensionSiteAccessComboboxModel : public ui::ComboboxModel { + public: + ExtensionSiteAccessComboboxModel(Browser* browser, + const extensions::Extension* extension); + + ExtensionSiteAccessComboboxModel(const ExtensionSiteAccessComboboxModel&) = + delete; + const ExtensionSiteAccessComboboxModel& operator=( + const ExtensionSiteAccessComboboxModel&) = delete; + + ~ExtensionSiteAccessComboboxModel() override; + + // Handles the action corresponding to the `selected_index`. + void HandleSelection(int selected_index); + + // Gets the combobox item index corresponding to the current site access. + int GetCurrentSiteAccessIndex() const; + + // ui::ComboboxModel: + int GetItemCount() const override; + std::u16string GetItemAt(int index) const override; + int GetDefaultIndex() const override; + bool IsItemEnabledAt(int index) const override; + + private: + // Checks if `extension_` is still valid by checking its + // status in the registry. + bool ExtensionIsValid() const; + + // Logs a user action when `site_access` is selected using the combobox. + void LogSiteAccessAction( + extensions::SitePermissionsHelper::SiteAccess site_access) const; + + const raw_ptr<Browser> browser_; + + // The extension associated with the combobox. + raw_ptr<const extensions::Extension> extension_; + + // Combobox drop down items. + std::vector<extensions::SitePermissionsHelper::SiteAccess> items_; +}; + +#endif // CHROME_BROWSER_UI_EXTENSIONS_EXTENSION_SITE_ACCESS_COMBOBOX_MODEL_H_
diff --git a/chrome/browser/ui/user_education/feature_promo_controller.h b/chrome/browser/ui/user_education/feature_promo_controller.h index 3556038a..32995fe4 100644 --- a/chrome/browser/ui/user_education/feature_promo_controller.h +++ b/chrome/browser/ui/user_education/feature_promo_controller.h
@@ -191,6 +191,8 @@ return critical_promo_bubble(); } + TutorialService* tutorial_service_for_testing() { return tutorial_service_; } + // Blocks a check whether the IPH would be created in an inactive window or // app before showing the IPH. Intended for browser and unit tests. // The actual implementation of the check is in the platform-specific
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial.cc b/chrome/browser/ui/user_education/tutorial/tutorial.cc index 536400f..ecba4f9 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial.cc +++ b/chrome/browser/ui/user_education/tutorial/tutorial.cc
@@ -65,8 +65,14 @@ } Tutorial::StepBuilder& Tutorial::StepBuilder::SetStepType( - ui::InteractionSequence::StepType step_type_) { + ui::InteractionSequence::StepType step_type_, + ui::CustomElementEventType event_type_) { + DCHECK_EQ(step_type_ == ui::InteractionSequence::StepType::kCustomEvent, + static_cast<bool>(event_type_)) + << "`event_type_` should be set if and only if `step_type_` is " + "kCustomEvent."; step_.step_type = step_type_; + step_.event_type = event_type_; return *this; } @@ -118,7 +124,7 @@ if (!step_.element_name.empty()) interaction_sequence_step_builder->SetElementName(step_.element_name); - interaction_sequence_step_builder->SetType(step_.step_type); + interaction_sequence_step_builder->SetType(step_.step_type, step_.event_type); if (step_.must_remain_visible.has_value()) interaction_sequence_step_builder->SetMustRemainVisible(
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial.h b/chrome/browser/ui/user_education/tutorial/tutorial.h index ac8b131..b4af884 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial.h +++ b/chrome/browser/ui/user_education/tutorial/tutorial.h
@@ -71,7 +71,10 @@ StepBuilder& SetAnchorElementName(std::string anchor_element_name); StepBuilder& SetTitleText(absl::optional<std::u16string> title_text_); StepBuilder& SetBodyText(std::u16string body_text_); - StepBuilder& SetStepType(ui::InteractionSequence::StepType step_type_); + // Sets the step type; `event_type_` should be set only for custom events. + StepBuilder& SetStepType( + ui::InteractionSequence::StepType step_type_, + ui::CustomElementEventType event_type_ = ui::CustomElementEventType()); StepBuilder& SetArrow(HelpBubbleArrow arrow_); StepBuilder& SetProgress(absl::optional<std::pair<int, int>> progress_); StepBuilder& SetIsLastStep(bool is_last_step_);
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_description.cc b/chrome/browser/ui/user_education/tutorial/tutorial_description.cc index 4c2d914..e24db86 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_description.cc +++ b/chrome/browser/ui/user_education/tutorial/tutorial_description.cc
@@ -26,12 +26,14 @@ ui::ElementIdentifier element_id_, std::string element_name_, HelpBubbleArrow arrow_, + ui::CustomElementEventType event_type_, absl::optional<bool> must_remain_visible_, bool transition_only_on_event_, TutorialDescription::NameElementsCallback name_elements_callback_) : title_text(title_text_), body_text(body_text_), step_type(step_type_), + event_type(event_type_), element_id(element_id_), element_name(element_name_), arrow(arrow_),
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_description.h b/chrome/browser/ui/user_education/tutorial/tutorial_description.h index 27f064e..da5ce67b 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_description.h +++ b/chrome/browser/ui/user_education/tutorial/tutorial_description.h
@@ -12,6 +12,7 @@ #include "chrome/browser/ui/user_education/help_bubble_params.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "ui/base/interaction/element_identifier.h" +#include "ui/base/interaction/element_tracker.h" #include "ui/base/interaction/interaction_sequence.h" // Holds the data required to properly store histograms for a given tutorial. @@ -118,6 +119,7 @@ ui::ElementIdentifier element_id_, std::string element_name_, HelpBubbleArrow arrow_, + ui::CustomElementEventType event_type_ = ui::CustomElementEventType(), absl::optional<bool> must_remain_visible_ = absl::nullopt, bool transition_only_on_event_ = false, NameElementsCallback name_elements_callback_ = NameElementsCallback()); @@ -130,17 +132,20 @@ // The text to to populated in the bubble. std::u16string body_text; - // the step type for InteractionSequence::Step. + // The step type for InteractionSequence::Step. ui::InteractionSequence::StepType step_type; - // the element used by interaction sequence to observe and attach a bubble. + // The event type for the step if `step_type` is kCustomEvent. + ui::CustomElementEventType event_type; + + // The element used by interaction sequence to observe and attach a bubble. ui::ElementIdentifier element_id; - // the element, referred to by name, used by the interaction sequence + // The element, referred to by name, used by the interaction sequence // to observe and potentially attach a bubble. must be non-empty. std::string element_name; - // the positioning of the bubble arrow + // The positioning of the bubble arrow. HelpBubbleArrow arrow = HelpBubbleArrow::kTopRight; // Should the element remain visible through the entire step, this should be
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_registry.cc b/chrome/browser/ui/user_education/tutorial/tutorial_registry.cc index 07eee03..6fb6220 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_registry.cc +++ b/chrome/browser/ui/user_education/tutorial/tutorial_registry.cc
@@ -46,3 +46,7 @@ TutorialDescription description) { tutorial_registry_.emplace(id, std::move(description)); } + +void TutorialRegistry::RemoveTutorialForTesting(TutorialIdentifier id) { + tutorial_registry_.erase(id); +}
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_registry.h b/chrome/browser/ui/user_education/tutorial/tutorial_registry.h index d15bd77..2bf76ca9 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_registry.h +++ b/chrome/browser/ui/user_education/tutorial/tutorial_registry.h
@@ -38,10 +38,14 @@ HelpBubbleFactoryRegistry* bubble_factory_registry, ui::ElementContext context); - // Adds a TutorialID, TutorialDescription Pair to the Registry. This should + // Adds a TutorialID, TutorialDescription pair to the registry. This should // be used by the RegisterTutorials method to Add Tutorials. void AddTutorial(TutorialIdentifier id, TutorialDescription description); + // Removes a TutorialID and its associated TutorialDescription from the + // registry, to clean up from tests that need to inject test-only tutorials. + void RemoveTutorialForTesting(TutorialIdentifier id); + private: std::map<TutorialIdentifier, TutorialDescription> tutorial_registry_; };
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_service.cc b/chrome/browser/ui/user_education/tutorial/tutorial_service.cc index 8d6b1aa..79dbe94 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_service.cc +++ b/chrome/browser/ui/user_education/tutorial/tutorial_service.cc
@@ -37,11 +37,12 @@ return true; } -void TutorialService::SetOnCompleteTutorial(CompletedCallback callback) { +void TutorialService::SetOnCompleteTutorialForTesting( + CompletedCallback callback) { completed_callback_ = std::move(callback); } -void TutorialService::SetOnAbortTutorial(AbortedCallback callback) { +void TutorialService::SetOnAbortTutorialForTesting(AbortedCallback callback) { aborted_callback_ = std::move(callback); }
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_service.h b/chrome/browser/ui/user_education/tutorial/tutorial_service.h index 89e9c4f0..6259978c 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_service.h +++ b/chrome/browser/ui/user_education/tutorial/tutorial_service.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/callback_forward.h" +#include "base/callback_helpers.h" #include "chrome/browser/ui/user_education/tutorial/tutorial.h" #include "chrome/browser/ui/user_education/tutorial/tutorial_identifier.h" #include "components/keyed_service/core/keyed_service.h" @@ -40,13 +41,14 @@ // Starts the tutorial by looking for the id in the Tutorial Registry. bool StartTutorial(TutorialIdentifier id, ui::ElementContext context); - void SetOnCompleteTutorial(CompletedCallback callback); - void SetOnAbortTutorial(AbortedCallback callback); + void SetOnCompleteTutorialForTesting(CompletedCallback callback); + void SetOnAbortTutorialForTesting(AbortedCallback callback); TutorialRegistry* tutorial_registry() { return tutorial_registry_; } private: friend class Tutorial; + friend class TutorialInteractiveUitest; // Aborts the current running tutorial if there is one. void AbortTutorial(); @@ -63,8 +65,8 @@ std::unique_ptr<Tutorial> running_tutorial_; // a function to call on complete of the tutorial - CompletedCallback completed_callback_; - AbortedCallback aborted_callback_; + CompletedCallback completed_callback_ = base::DoNothing(); + AbortedCallback aborted_callback_ = base::DoNothing(); std::unique_ptr<HelpBubble> currently_displayed_bubble_;
diff --git a/chrome/browser/ui/user_education/tutorial/tutorial_unittest.cc b/chrome/browser/ui/user_education/tutorial/tutorial_unittest.cc index fa028945..d17e774 100644 --- a/chrome/browser/ui/user_education/tutorial/tutorial_unittest.cc +++ b/chrome/browser/ui/user_education/tutorial/tutorial_unittest.cc
@@ -22,6 +22,7 @@ namespace { DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestIdentifier1); +DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kCustomEventType1); const char kTestElementName1[] = "ELEMENT_NAME_1"; @@ -110,7 +111,7 @@ CreateTestTutorialBubbleFactoryRegistry(); TutorialRegistry registry; TutorialService service(®istry, bubble_factory_registry.get()); - service.SetOnCompleteTutorial(completed.Get()); + service.SetOnCompleteTutorialForTesting(completed.Get()); // build elements and keep them for triggering show/hide ui::TestElement element_1(kTestIdentifier1, kTestContext1); @@ -128,3 +129,31 @@ completed, Run, service.StartTutorial(kTestTutorial1, element_1.context())); } + +TEST(TutorialTest, TutorialWithCustomEvent) { + UNCALLED_MOCK_CALLBACK(TutorialService::CompletedCallback, completed); + + const auto bubble_factory_registry = + CreateTestTutorialBubbleFactoryRegistry(); + TutorialRegistry registry; + TutorialService service(®istry, bubble_factory_registry.get()); + service.SetOnCompleteTutorialForTesting(completed.Get()); + + // build elements and keep them for triggering show/hide + ui::TestElement element_1(kTestIdentifier1, kTestContext1); + element_1.Show(); + + // Build the tutorial Description + TutorialDescription description; + description.steps.emplace_back(TutorialDescription::Step( + u"step 1 title", u"step 1 description", + ui::InteractionSequence::StepType::kCustomEvent, kTestIdentifier1, "", + HelpBubbleArrow::kNone, kCustomEventType1)); + registry.AddTutorial(kTestTutorial1, std::move(description)); + + service.StartTutorial(kTestTutorial1, element_1.context()); + EXPECT_CALL_IN_SCOPE( + completed, Run, + ui::ElementTracker::GetFrameworkDelegate()->NotifyCustomEvent( + &element_1, kCustomEventType1)); +}
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc b/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc index 40552fd..d68a8b7 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_item_view.cc
@@ -10,9 +10,9 @@ #include "base/metrics/user_metrics.h" #include "base/metrics/user_metrics_action.h" #include "chrome/app/vector_icons/vector_icons.h" -#include "chrome/browser/extensions/site_permissions_helper.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/extensions/extension_site_access_combobox_model.h" #include "chrome/browser/ui/toolbar/toolbar_action_view_controller.h" #include "chrome/browser/ui/toolbar/toolbar_actions_model.h" #include "chrome/browser/ui/views/bubble_menu_item_factory.h" @@ -20,6 +20,7 @@ #include "chrome/browser/ui/views/extensions/extensions_menu_button.h" #include "chrome/browser/ui/views/hover_button.h" #include "chrome/grit/generated_resources.h" +#include "content/public/browser/web_contents.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/metadata/metadata_impl_macros.h" #include "ui/color/color_id.h" @@ -33,6 +34,7 @@ #include "ui/views/border.h" #include "ui/views/controls/button/button.h" #include "ui/views/controls/button/menu_button_controller.h" +#include "ui/views/controls/combobox/combobox.h" #include "ui/views/layout/flex_layout.h" #include "ui/views/layout/flex_layout_types.h" #include "ui/views/vector_icons.h" @@ -70,11 +72,11 @@ std::unique_ptr<ToolbarActionViewController> controller, bool allow_pinning) : item_type_(item_type), - profile_(browser->profile()), + browser_(browser), primary_action_button_( new ExtensionsMenuButton(browser, controller.get(), allow_pinning)), controller_(std::move(controller)), - model_(ToolbarActionsModel::Get(profile_)) { + model_(ToolbarActionsModel::Get(browser_->profile())) { // Items with kSiteAccess type should only be created if their // associated extension has or requests access to the current page. if (item_type == MenuItemType::kSiteAccess) { @@ -101,8 +103,9 @@ if (item_type_ == MenuItemType::kExtensions) { AddPinButton(); AddContextMenuButton(); + } else { + AddSiteAccessCombobox(); } - // TODO(crbug.com/1263310): Add a dropdown view for MenuItemType::kSiteAccess. } ExtensionsMenuItemView::~ExtensionsMenuItemView() = default; @@ -139,7 +142,8 @@ pin_button_->SetTooltipText(l10n_util::GetStringUTF16(pin_button_string_id)); // Extension pinning is not available in Incognito as it leaves a trace of // user activity. - pin_button_->SetEnabled(!is_force_pinned && !profile_->IsOffTheRecord()); + pin_button_->SetEnabled(!is_force_pinned && + !browser_->profile()->IsOffTheRecord()); if (!GetWidget()) return; @@ -185,6 +189,18 @@ IsPinned() ? IDS_EXTENSION_PINNED : IDS_EXTENSION_UNPINNED)); } +void ExtensionsMenuItemView::Update() { + view_controller()->UpdateState(); + if (item_type_ == MenuItemType::kSiteAccess) { + content::WebContents* web_contents = + browser_->tab_strip_model()->GetActiveWebContents(); + if (!web_contents) + return; + int index = site_access_combobox_model_->GetCurrentSiteAccessIndex(); + site_access_combobox_->SetSelectedIndex(index); + } +} + ExtensionsMenuButton* ExtensionsMenuItemView::primary_action_button_for_testing() { return primary_action_button_; @@ -231,6 +247,34 @@ context_menu_button_ = AddChildView(std::move(context_menu_button)); } +void ExtensionsMenuItemView::AddSiteAccessCombobox() { + DCHECK_EQ(item_type_, MenuItemType::kSiteAccess); + + auto* extension = extensions::ExtensionRegistry::Get(browser_->profile()) + ->enabled_extensions() + .GetByID(controller_->GetId()); + + auto combobox_model = + std::make_unique<ExtensionSiteAccessComboboxModel>(browser_, extension); + site_access_combobox_model_ = combobox_model.get(); + + auto combobox = std::make_unique<views::Combobox>(std::move(combobox_model)); + site_access_combobox_ = AddChildView(std::move(combobox)); + + site_access_combobox_->SetAccessibleName(l10n_util::GetStringUTF16( + IDS_ACCNAME_EXTENSIONS_MENU_SITE_ACCESS_COMBOBOX)); + site_access_combobox_->SetCallback( + base::BindRepeating(&ExtensionsMenuItemView::OnComboboxSelectionChanged, + base::Unretained(this))); +} + +void ExtensionsMenuItemView::OnComboboxSelectionChanged() { + DCHECK_EQ(item_type_, MenuItemType::kSiteAccess); + + int selected_index = site_access_combobox_->GetSelectedIndex(); + site_access_combobox_model_->HandleSelection(selected_index); +} + SkColor ExtensionsMenuItemView::GetAdjustedIconColor(SkColor icon_color) const { const SkColor background_color = GetColorProvider()->GetColor(ui::kColorBubbleBackground);
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_item_view.h b/chrome/browser/ui/views/extensions/extensions_menu_item_view.h index fe681f2..51e387b5 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_item_view.h +++ b/chrome/browser/ui/views/extensions/extensions_menu_item_view.h
@@ -8,6 +8,7 @@ #include <memory> #include "base/memory/raw_ptr.h" +#include "chrome/browser/ui/extensions/extension_site_access_combobox_model.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/views/view.h" @@ -15,9 +16,13 @@ class ExtensionContextMenuController; class ExtensionsMenuButton; class HoverButton; -class Profile; class ToolbarActionViewController; class ToolbarActionsModel; +class ExtensionSiteAccessComboboxModel; + +namespace views { +class Combobox; +} // namespace views // ExtensionsMenuItemView is a single row inside the extensions menu for a // particular extension. Includes information about the extension in addition to @@ -51,6 +56,9 @@ // views::View: void OnThemeChanged() override; + // Updates the controller and child views to be on sync with the parent views. + void Update(); + // Updates the pin button. `item_type_` must be `ItemType::kExtensions`. void UpdatePinButton(); @@ -76,6 +84,9 @@ return context_menu_button_; } HoverButton* pin_button_for_testing() { return pin_button_; } + views::Combobox* site_access_combobox_for_testing() { + return site_access_combobox_; + } private: // Adds a pin button as a child view. `item_type_` must be @@ -86,27 +97,44 @@ // `ItemType::kExtensions`. void AddContextMenuButton(); + // Adds a site access combobox as a child view. `item_type_` must be + // `ItemType::kSiteAccess`. + void AddSiteAccessCombobox(); + + // Handles the selection of a combobox option. `item_type_` must be + // `ItemType::kSiteAccess`. + void OnComboboxSelectionChanged(); + // Maybe adjust |icon_color| to assure high enough contrast with the // background. SkColor GetAdjustedIconColor(SkColor icon_color) const; + // Determines which views will be added as children of this item view. const MenuItemType item_type_; - const raw_ptr<Profile> profile_; + const raw_ptr<Browser> browser_; + // Extension action button present in `ItemType::kSiteAccess` and + // `ItemType::kExtensions`. const raw_ptr<ExtensionsMenuButton> primary_action_button_; - - std::unique_ptr<ToolbarActionViewController> controller_; - - raw_ptr<HoverButton> context_menu_button_ = nullptr; - - const raw_ptr<ToolbarActionsModel> model_; - + // Pin button present in `ItemType::kExtensions`. raw_ptr<HoverButton> pin_button_ = nullptr; + // Context menu button present in `ItemType::kExtensions`. + raw_ptr<HoverButton> context_menu_button_ = nullptr; + // Dropdown list present in `ItemType::kSiteAccess`. + raw_ptr<views::Combobox> site_access_combobox_ = nullptr; - // This controller is responsible for showing the context menu for an - // extension. + // Controller responsible for an action that is shown in the toolbar. + std::unique_ptr<ToolbarActionViewController> controller_; + // Controller responsible for showing the context menu for an extension. std::unique_ptr<ExtensionContextMenuController> context_menu_controller_; + + // Model for the browser actions toolbar that provides information such as the + // action pin status or visibility. + const raw_ptr<ToolbarActionsModel> model_; + // Model for `site_access_combobox_` to select an option. + raw_ptr<ExtensionSiteAccessComboboxModel> site_access_combobox_model_ = + nullptr; }; #endif // CHROME_BROWSER_UI_VIEWS_EXTENSIONS_EXTENSIONS_MENU_ITEM_VIEW_H_
diff --git a/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc b/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc index 2a24f9a3..b6fd518 100644 --- a/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc +++ b/chrome/browser/ui/views/extensions/extensions_menu_view_interactive_uitest.cc
@@ -565,11 +565,12 @@ EXPECT_NE(nullptr, extensions_container->GetPoppedOutAction()); - // Verify the context menu option is to unpin the extension. + // Verify the context menu option, when opened from the toolbar action, is to + // unpin the extension. ui::SimpleMenuModel* context_menu = static_cast<ui::SimpleMenuModel*>( extensions_container->GetActionForId(extensions()[0]->id()) ->GetContextMenu(extensions::ExtensionContextMenuModel:: - ContextMenuSource::kMenuItem)); + ContextMenuSource::kToolbarAction)); int visibility_index = context_menu->GetIndexOfCommandId( extensions::ExtensionContextMenuModel::TOGGLE_VISIBILITY); ASSERT_GE(visibility_index, 0); @@ -596,11 +597,12 @@ ASSERT_EQ(1u, visible_icons.size()); EXPECT_NE(nullptr, extensions_container->GetPoppedOutAction()); - // Verify the context menu option is to unpin the extension. + // Verify the context menu option, when opened from the toolbar action, is to + // unpin the extension. ui::SimpleMenuModel* context_menu = static_cast<ui::SimpleMenuModel*>( extensions_container->GetActionForId(extensions()[0]->id()) ->GetContextMenu(extensions::ExtensionContextMenuModel:: - ContextMenuSource::kMenuItem)); + ContextMenuSource::kToolbarAction)); int visibility_index = context_menu->GetIndexOfCommandId( extensions::ExtensionContextMenuModel::TOGGLE_VISIBILITY); ASSERT_GE(visibility_index, 0);
diff --git a/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.cc b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.cc index e78a2f9..d781e186 100644 --- a/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.cc +++ b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.cc
@@ -112,7 +112,8 @@ // Updates the `item_view` state and its position under `parent_view`. void UpdateMenuItemView(ExtensionsMenuItemView* item_view, views::View* parent_view) { - item_view->view_controller()->UpdateState(); + item_view->Update(); + int new_index = FindIndex(item_view->view_controller()->GetActionName(), parent_view); parent_view->ReorderChildView(item_view, new_index); @@ -366,20 +367,22 @@ } void ExtensionsTabbedMenuView::Update() { - auto update_items = [](views::View* parent_view) { - for (views::View* view : parent_view->children()) { - auto* item_view = GetAsMenuItemView(view); - UpdateMenuItemView(item_view, parent_view); - } - }; + // An extension that previously did not want access, and therefore was not in + // a site access section, may want access now. This means moving existent + // items between sections is not sufficient. Therefore, we need to clear the + // site access sections and re-insert items in the correct place. + requests_access_.items->RemoveAllChildViews(); + has_access_.items->RemoveAllChildViews(); - update_items(installed_items_); - update_items(requests_access_.items); - update_items(has_access_.items); - - MoveItemsBetweenSectionsIfNecessary(); + for (views::View* view : installed_items_->children()) { + auto* item_view = GetAsMenuItemView(view); + UpdateMenuItemView(item_view, installed_items_); + MaybeCreateAndInsertSiteAccessItem(item_view->view_controller()->GetId()); + } UpdateSiteAccessSectionsVisibility(); + + ConsistencyCheck(); } void ExtensionsTabbedMenuView::CreateSiteAccessTab() { @@ -578,21 +581,25 @@ #if DCHECK_IS_ON() const base::flat_set<std::string>& action_ids = toolbar_model_->action_ids(); - // Check that all items are owned by the view hierarchy, and that each - // corresponds to an item in the model. - std::vector<std::u16string> installed_items_names; - for (views::View* view : installed_items_->children()) { - DCHECK(Contains(view)); - auto* installed_item_view = GetAsMenuItemView(view); - DCHECK(base::Contains(action_ids, - installed_item_view->view_controller()->GetId())); - installed_items_names.push_back(base::i18n::ToLower( - installed_item_view->view_controller()->GetActionName())); - } + auto check_items = [action_ids, this](views::View* parent_view) { + // Check that all items are owned by the view hierarchy, and that each + // corresponds to an item in the model. + std::vector<std::u16string> item_names; + for (views::View* view : parent_view->children()) { + DCHECK(Contains(view)); + auto* item_view = GetAsMenuItemView(view); + DCHECK(base::Contains(action_ids, item_view->view_controller()->GetId())); + item_names.push_back( + base::i18n::ToLower(item_view->view_controller()->GetActionName())); + } - // Verify that all installed extensions are properly sorted. - DCHECK(std::is_sorted(installed_items_names.begin(), - installed_items_names.end())); + // Verify that all items are properly sorted. + DCHECK(std::is_sorted(item_names.begin(), item_names.end())); + }; + + check_items(installed_items_); + check_items(requests_access_.items); + check_items(has_access_.items); #endif }
diff --git a/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view_unittest.cc b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view_unittest.cc index ab3ec67..08166f3 100644 --- a/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view_unittest.cc +++ b/chrome/browser/ui/views/extensions/extensions_tabbed_menu_view_unittest.cc
@@ -4,23 +4,36 @@ #include "chrome/browser/ui/views/extensions/extensions_tabbed_menu_view.h" +#include <string> + #include "base/feature_list.h" #include "base/test/metrics/user_action_tester.h" #include "build/build_config.h" #include "chrome/browser/extensions/chrome_test_extension_loader.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/extensions/site_permissions_helper.h" #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/views/extensions/extensions_menu_button.h" #include "chrome/browser/ui/views/extensions/extensions_menu_item_view.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_unittest.h" +#include "chrome/test/base/ui_test_utils.h" +#include "content/public/browser/notification_service.h" +#include "content/public/test/test_utils.h" +#include "extensions/browser/notification_types.h" #include "extensions/browser/test_extension_registry_observer.h" #include "extensions/common/extension_urls.h" #include "extensions/test/test_extension_dir.h" +#include "testing/gmock/include/gmock/gmock.h" +#include "ui/views/controls/combobox/combobox.h" #include "ui/views/view_utils.h" namespace { +constexpr int kOnClickComboboxIndex = 0; +constexpr int kOnSiteComboboxIndex = 1; +constexpr int kOnAllSitesComboboxIndex = 2; + // A scoper that manages a Browser instance created by BrowserWithTestWindowTest // beyond the default instance it creates in SetUp. class AdditionalBrowser { @@ -98,19 +111,25 @@ ->GetRequestsAccessItemsForTesting(); } - // Asserts there is exactly 1 menu item and then returns it. + // Asserts there is exactly one installed menu item and then returns it. ExtensionsMenuItemView* GetOnlyInstalledMenuItem(); + // Asserts there is exactly one has access menu item and then returns it. + ExtensionsMenuItemView* GetOnlyHasAccessMenuItem(); + // Asserts there is exactly one requests access menu item and then returns it. + ExtensionsMenuItemView* GetOnlyRequestsAccessMenuItem(); // Opens the tabbed menu in the installed tab. void ShowInstalledTabInMenu(); - // Opens the tabbed menu in the site access tab. void ShowSiteAccessTabInMenu(); void ClickSiteAccessButton(); void ClickExtensionsButton(); + void ClickPrimaryActionButton(ExtensionsMenuItemView* item); void ClickPinButton(ExtensionsMenuItemView* installed_item); void ClickContextMenuButton(ExtensionsMenuItemView* installed_item); + void SelectSiteAccessInCombobox(ExtensionsMenuItemView* site_access_item, + int index); void LayoutMenuIfNecessary() { extensions_tabbed_menu()->GetWidget()->LayoutRootViewIfNecessary(); @@ -146,6 +165,26 @@ return *items.begin(); } +ExtensionsMenuItemView* +ExtensionsTabbedMenuViewUnitTest::GetOnlyHasAccessMenuItem() { + std::vector<ExtensionsMenuItemView*> items = has_access_items(); + if (items.size() != 1u) { + ADD_FAILURE() << "Not exactly one item; size is: " << items.size(); + return nullptr; + } + return *items.begin(); +} + +ExtensionsMenuItemView* +ExtensionsTabbedMenuViewUnitTest::GetOnlyRequestsAccessMenuItem() { + std::vector<ExtensionsMenuItemView*> items = requests_access_items(); + if (items.size() != 1u) { + ADD_FAILURE() << "Not exactly one item; size is: " << items.size(); + return nullptr; + } + return *items.begin(); +} + void ExtensionsTabbedMenuViewUnitTest::ShowInstalledTabInMenu() { ExtensionsTabbedMenuView::ShowBubble( extensions_button(), browser(), extensions_container(), @@ -168,6 +207,12 @@ LayoutContainerIfNecessary(); } +void ExtensionsTabbedMenuViewUnitTest::ClickPrimaryActionButton( + ExtensionsMenuItemView* item) { + ClickButton(item->primary_action_button_for_testing()); + WaitForAnimation(); +} + void ExtensionsTabbedMenuViewUnitTest::ClickPinButton( ExtensionsMenuItemView* installed_item) { ClickButton(installed_item->pin_button_for_testing()); @@ -179,6 +224,17 @@ ClickButton(installed_item->context_menu_button_for_testing()); } +void ExtensionsTabbedMenuViewUnitTest::SelectSiteAccessInCombobox( + ExtensionsMenuItemView* site_access_item, + int index) { + content::WindowedNotificationObserver permissions_observer( + extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, + content::NotificationService::AllSources()); + site_access_item->site_access_combobox_for_testing()->SetSelectedRow(index); + permissions_observer.Wait(); + LayoutMenuIfNecessary(); +} + TEST_F(ExtensionsTabbedMenuViewUnitTest, ButtonOpensAndClosesCorrespondingTab) { // Load an extension with all urls permissions so the site access button is // visible. @@ -302,7 +358,7 @@ ASSERT_TRUE(installed_item); ToolbarActionViewController* controller = installed_item->view_controller(); EXPECT_FALSE(extensions_container()->IsActionVisibleOnToolbar(controller)); - EXPECT_EQ(GetPinnedExtensionNames(), std::vector<std::string>{}); + EXPECT_THAT(GetPinnedExtensionNames(), testing::IsEmpty()); ClickPinButton(installed_item); @@ -313,7 +369,7 @@ EXPECT_FALSE(extensions_container()->IsActionVisibleOnToolbar( installed_item->view_controller())); - EXPECT_EQ(GetPinnedExtensionNames(), std::vector<std::string>{}); + EXPECT_THAT(GetPinnedExtensionNames(), testing::IsEmpty()); } TEST_F(ExtensionsTabbedMenuViewUnitTest, @@ -468,7 +524,7 @@ WaitForAnimation(); EXPECT_EQ(installed_items().size(), 0u); - EXPECT_EQ(GetPinnedExtensionNames(), std::vector<std::string>{}); + EXPECT_THAT(GetPinnedExtensionNames(), testing::IsEmpty()); EnableExtension(extension_id); LayoutMenuIfNecessary(); @@ -589,7 +645,7 @@ // forbidden websites such as chrome:-scheme), and it should be in the has // access section. ASSERT_EQ(has_access_items().size(), 1u); - EXPECT_EQ(base::UTF16ToUTF8((*has_access_items().begin()) + EXPECT_EQ(base::UTF16ToUTF8(GetOnlyHasAccessMenuItem() ->primary_action_button_for_testing() ->label_text_for_testing()), kHasAccessName); @@ -598,6 +654,152 @@ EXPECT_EQ(requests_access_items().size(), 0u); } +TEST_F( + ExtensionsTabbedMenuViewUnitTest, + SiteAccessTab_ExtensionInCorrectSiteAccessSectionAfterChangingSiteAccessUsingCombobox) { + constexpr char kExtensionName[] = "Has Access Extension"; + InstallExtensionWithHostPermissions(kExtensionName, {"<all_urls>"}); + + const GURL url_a("http://www.a.com"); + web_contents_tester()->NavigateAndCommit(url_a); + ShowSiteAccessTabInMenu(); + + // Verify extension is in the "has access" section with "on all sites" access. + ASSERT_EQ(has_access_items().size(), 1u); + ASSERT_EQ(requests_access_items().size(), 0u); + EXPECT_EQ(GetOnlyHasAccessMenuItem() + ->site_access_combobox_for_testing() + ->GetSelectedIndex(), + kOnAllSitesComboboxIndex); + + // Change extension's site access to run "on site" using the combobox. + SelectSiteAccessInCombobox(GetOnlyHasAccessMenuItem(), kOnSiteComboboxIndex); + + // Verify extension is in the "has access" section with "on site" access. + ASSERT_EQ(has_access_items().size(), 1u); + ASSERT_EQ(requests_access_items().size(), 0u); + EXPECT_EQ(GetOnlyHasAccessMenuItem() + ->site_access_combobox_for_testing() + ->GetSelectedIndex(), + kOnSiteComboboxIndex); + + // Change extension's site access to run "on click" using the combobox. + SelectSiteAccessInCombobox(GetOnlyHasAccessMenuItem(), kOnClickComboboxIndex); + + // Verify extension is in the "requests access" section with "on click" + // access. + ASSERT_EQ(has_access_items().size(), 0u); + ASSERT_EQ(requests_access_items().size(), 1u); + EXPECT_EQ(GetOnlyRequestsAccessMenuItem() + ->site_access_combobox_for_testing() + ->GetSelectedIndex(), + kOnClickComboboxIndex); +} + +TEST_F( + ExtensionsTabbedMenuViewUnitTest, + SiteAccessTab_ExtensionInCorrectSiteAccessSectionAfterChangingSiteAccessUsingContextMenu) { + constexpr char kExtensionName[] = "Has Access Extension"; + auto extension = + InstallExtensionWithHostPermissions(kExtensionName, {"<all_urls>"}); + + const GURL url_a("http://www.a.com"); + web_contents_tester()->NavigateAndCommit(url_a); + ShowSiteAccessTabInMenu(); + + extensions::ExtensionContextMenuModel menu( + extension.get(), browser(), extensions::ExtensionContextMenuModel::PINNED, + nullptr, true, + extensions::ExtensionContextMenuModel::ContextMenuSource::kToolbarAction); + + // Verify extension is in the "has access" section with "on all sites" access. + ASSERT_EQ(has_access_items().size(), 1u); + ASSERT_EQ(requests_access_items().size(), 0u); + EXPECT_EQ(GetOnlyHasAccessMenuItem() + ->site_access_combobox_for_testing() + ->GetSelectedIndex(), + kOnAllSitesComboboxIndex); + + // Change extension's site access to run "on site" using the context menu. + { + content::WindowedNotificationObserver permissions_observer( + extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, + content::NotificationService::AllSources()); + menu.ExecuteCommand( + extensions::ExtensionContextMenuModel::PAGE_ACCESS_RUN_ON_SITE, 0); + permissions_observer.Wait(); + LayoutMenuIfNecessary(); + } + + // Verify extension is in the "has access" section with "on site" access. + ASSERT_EQ(has_access_items().size(), 1u); + ASSERT_EQ(requests_access_items().size(), 0u); + EXPECT_EQ(GetOnlyHasAccessMenuItem() + ->site_access_combobox_for_testing() + ->GetSelectedIndex(), + kOnSiteComboboxIndex); + + // Change extension's site access to run "on click" using the context menu. + { + content::WindowedNotificationObserver permissions_observer( + extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, + content::NotificationService::AllSources()); + menu.ExecuteCommand( + extensions::ExtensionContextMenuModel::PAGE_ACCESS_RUN_ON_CLICK, 0); + permissions_observer.Wait(); + LayoutMenuIfNecessary(); + } + + // Verify extension is in the "requests access" section with "on click" + // access. + ASSERT_EQ(has_access_items().size(), 0u); + ASSERT_EQ(requests_access_items().size(), 1u); + EXPECT_EQ(GetOnlyRequestsAccessMenuItem() + ->site_access_combobox_for_testing() + ->GetSelectedIndex(), + kOnClickComboboxIndex); +} + +TEST_F( + ExtensionsTabbedMenuViewUnitTest, + SiteAccessTab_ExtensionsInCorrectSiteAccessSectionAfterClickingOnAction) { + constexpr char kExtensionName[] = "Has Access Extension"; + InstallExtensionWithHostPermissions(kExtensionName, {"<all_urls>"}); + + const GURL url_a("http://www.a.com"); + web_contents_tester()->NavigateAndCommit(url_a); + ShowSiteAccessTabInMenu(); + + // Change extension's site access to run "on click" using the combobox. By + // default, extension has site access. + SelectSiteAccessInCombobox(GetOnlyHasAccessMenuItem(), kOnClickComboboxIndex); + + // Verify extension is in the "requests access" section with "on click" + // access. + ASSERT_EQ(has_access_items().size(), 0u); + ASSERT_EQ(requests_access_items().size(), 1u); + EXPECT_EQ(GetOnlyRequestsAccessMenuItem() + ->site_access_combobox_for_testing() + ->GetSelectedIndex(), + kOnClickComboboxIndex); + + // Run extensions action by clicking on it. + content::WindowedNotificationObserver permissions_observer( + extensions::NOTIFICATION_EXTENSION_PERMISSIONS_UPDATED, + content::NotificationService::AllSources()); + ClickPrimaryActionButton(GetOnlyRequestsAccessMenuItem()); + permissions_observer.Wait(); + LayoutMenuIfNecessary(); + + // Verify extension is in the "has access" section with "on click" access. + ASSERT_EQ(has_access_items().size(), 1u); + ASSERT_EQ(requests_access_items().size(), 0u); + EXPECT_EQ(GetOnlyHasAccessMenuItem() + ->site_access_combobox_for_testing() + ->GetSelectedIndex(), + kOnClickComboboxIndex); +} + TEST_F(ExtensionsTabbedMenuViewUnitTest, SiteAccessTab_AddAndRemoveExtensionWhenMenuIsOpen) { constexpr char kExtensionA[] = "A Extension"; @@ -647,8 +849,79 @@ } } -// TODO(crbug.com/1263310): Verify menu gets updated after permission changes -// using the menu item dropdown. +TEST_F(ExtensionsTabbedMenuViewUnitTest, + SiteAccessTab_TabChangesWithExtensionMenuOpen) { + constexpr char kExtension[] = "Test Extension"; + const GURL url_a("http://www.a.com"); + const GURL url_b("http://www.b.com"); + const GURL url_c("http://www.c.com"); + + InstallExtensionWithHostPermissions( + kExtension, {url_a.spec(), url_b.spec(), url_c.spec()}); + ShowSiteAccessTabInMenu(); + + // Navigate to a url where the extension does not want access. + const GURL url_no_access("http://www.noaccess.com"); + web_contents_tester()->NavigateAndCommit(url_no_access); + LayoutMenuIfNecessary(); + ASSERT_TRUE(ExtensionsTabbedMenuView::IsShowing()); + + // Verify site access sections are empty. + { + EXPECT_THAT(GetNamesFromMenuItems(has_access_items()), testing::IsEmpty()); + EXPECT_THAT(GetNamesFromMenuItems(requests_access_items()), + testing::IsEmpty()); + } + + // Navigate to a url where the extension wants access. + web_contents_tester()->NavigateAndCommit(url_a); + LayoutMenuIfNecessary(); + ASSERT_TRUE(ExtensionsTabbedMenuView::IsShowing()); + + // Verify the extension is in the "has access" section with "on site" + // access. + { + EXPECT_THAT(GetNamesFromMenuItems(has_access_items()), + testing::ElementsAre(kExtension)); + EXPECT_THAT(GetNamesFromMenuItems(requests_access_items()), + testing::IsEmpty()); + EXPECT_THAT(GetOnlyHasAccessMenuItem() + ->site_access_combobox_for_testing() + ->GetSelectedIndex(), + kOnSiteComboboxIndex); + } + + // Navigate to a url where the extension keeps its current access. + web_contents_tester()->NavigateAndCommit(url_b); + LayoutMenuIfNecessary(); + ASSERT_TRUE(ExtensionsTabbedMenuView::IsShowing()); + + // Verify the extension is still in "has access" section with "on site" + // access. + { + EXPECT_THAT(GetNamesFromMenuItems(has_access_items()), + testing::ElementsAre(kExtension)); + EXPECT_THAT(GetNamesFromMenuItems(requests_access_items()), + testing::IsEmpty()); + EXPECT_EQ(GetOnlyHasAccessMenuItem() + ->site_access_combobox_for_testing() + ->GetSelectedIndex(), + kOnSiteComboboxIndex); + } + + // Navigate to a url where the extension can't access. + const GURL chrome_url("chrome://extensions"); + web_contents_tester()->NavigateAndCommit(chrome_url); + LayoutMenuIfNecessary(); + ASSERT_TRUE(ExtensionsTabbedMenuView::IsShowing()); + + // Verify site access sections are empty. + { + EXPECT_THAT(GetNamesFromMenuItems(has_access_items()), testing::IsEmpty()); + EXPECT_THAT(GetNamesFromMenuItems(requests_access_items()), + testing::IsEmpty()); + } +} TEST_F(ExtensionsTabbedMenuViewUnitTest, WindowTitle) { InstallExtension("Test Extension");
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc index 65d648f..07c8eba8 100644 --- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc +++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
@@ -20,7 +20,6 @@ #include "base/task/thread_pool.h" #include "base/win/windows_version.h" #include "chrome/browser/browser_process.h" -#include "chrome/browser/headless/headless_mode_util.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/profiles/profile_avatar_icon_util.h" #include "chrome/browser/profiles/profile_manager.h" @@ -284,10 +283,7 @@ else OnHostWorkspaceChanged(); } - // Avoid changing desktop window visibility state when browser is running in - // native headless mode. - if (!headless::IsChromeNativeHeadless()) - DesktopWindowTreeHostWin::Show(show_state, restore_bounds); + DesktopWindowTreeHostWin::Show(show_state, restore_bounds); } std::string BrowserDesktopWindowTreeHostWin::GetWorkspace() const {
diff --git a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc index 66357df..bd3b1e6 100644 --- a/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc +++ b/chrome/browser/ui/views/tab_sharing/tab_sharing_ui_views.cc
@@ -473,34 +473,32 @@ } // Determine if we are currently allowed to share this tab by policy. - const bool is_sharing_allowed_by_policy = + bool is_sharing_allowed_by_policy = !capturer_restricted_to_same_origin_ || capturer_origin_.IsSameOriginWith( contents->GetMainFrame()->GetLastCommittedOrigin()); - // Never show the [share this tab instead] if sharing is not possible or is - // blocked by policy. - const bool can_show_share_instead_button = - is_share_instead_button_possible && is_sharing_allowed_by_policy; - - TabSharingInfoBarDelegate::ButtonState share_this_tab_instead_button_state = - can_show_share_instead_button - ? TabSharingInfoBarDelegate::ButtonState::ENABLED - : TabSharingInfoBarDelegate::ButtonState::NOT_SHOWN; - #if BUILDFLAG(IS_CHROMEOS) - const bool dlp_enabled = - g_apply_dlp_for_all_users_for_testing_ || - policy::DlpRulesManagerFactory::GetForPrimaryProfile(); - const bool screenshare_allowed_by_dlp = - !dlp_enabled || - !policy::DlpContentManager::Get()->IsScreenShareBlocked(contents); - if (!screenshare_allowed_by_dlp && can_show_share_instead_button) { - share_this_tab_instead_button_state = - TabSharingInfoBarDelegate::ButtonState::DISABLED; + // Check if dlp policies allow sharing. + // This check is skipped if sharing is already forbidden. + if (is_sharing_allowed_by_policy) { + const bool dlp_enabled = + g_apply_dlp_for_all_users_for_testing_ || + policy::DlpRulesManagerFactory::GetForPrimaryProfile(); + if (dlp_enabled && + policy::DlpContentManager::Get()->IsScreenShareBlocked(contents)) { + is_sharing_allowed_by_policy = false; + } } #endif + TabSharingInfoBarDelegate::ButtonState share_this_tab_instead_button_state = + !is_share_instead_button_possible + ? TabSharingInfoBarDelegate::ButtonState::NOT_SHOWN + : is_sharing_allowed_by_policy + ? TabSharingInfoBarDelegate::ButtonState::ENABLED + : TabSharingInfoBarDelegate::ButtonState::DISABLED; + infobars_[contents] = TabSharingInfoBarDelegate::Create( infobar_manager, shared_tab_name_, app_name_, shared_tab_ == contents /*shared_tab*/,
diff --git a/chrome/browser/ui/views/tabs/tab_container.cc b/chrome/browser/ui/views/tabs/tab_container.cc new file mode 100644 index 0000000..f335975 --- /dev/null +++ b/chrome/browser/ui/views/tabs/tab_container.cc
@@ -0,0 +1,10 @@ +// Copyright 2022 The Chromium 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/tabs/tab_container.h" + +#include "ui/base/metadata/metadata_impl_macros.h" + +BEGIN_METADATA(TabContainer, views::View) +END_METADATA
diff --git a/chrome/browser/ui/views/tabs/tab_container.h b/chrome/browser/ui/views/tabs/tab_container.h new file mode 100644 index 0000000..0848fc9 --- /dev/null +++ b/chrome/browser/ui/views/tabs/tab_container.h
@@ -0,0 +1,22 @@ +// Copyright 2022 The Chromium 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_VIEWS_TABS_TAB_CONTAINER_H_ +#define CHROME_BROWSER_UI_VIEWS_TABS_TAB_CONTAINER_H_ + +#include "ui/base/metadata/metadata_header_macros.h" +#include "ui/views/view.h" + +// A View that contains a sequence of Tabs for the TabStrip. +class TabContainer : public views::View { + public: + METADATA_HEADER(TabContainer); + + TabContainer() = default; + ~TabContainer() override = default; + + private: +}; + +#endif // CHROME_BROWSER_UI_VIEWS_TABS_TAB_CONTAINER_H_
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 1f9590de..203fe76 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -70,6 +70,10 @@ #include "ui/wm/core/window_modality_controller.h" // nogncheck #endif +#if defined(USE_OZONE) +#include "ui/ozone/public/ozone_platform.h" +#endif + using content::OpenURLParams; using content::WebContents; @@ -84,6 +88,22 @@ // maximized size. constexpr int kMaximizedWindowInset = 10; // DIPs. +// Some platforms, such as Lacros and Desktop Linux with Wayland, disallow +// client applications to manipulate absolute screen positions, by design. +// Preventing, for example, clients from programmatically positioning toplevel +// windows using absolute coordinates. By default, this class assumes that the +// underlying platform supports it, unless indicated by the Ozone platform +// properties. +bool PlatformProvidesAbsoluteWindowPositions() { +#if defined(USE_OZONE) + return ui::OzonePlatform::GetInstance() + ->GetPlatformProperties() + .supports_global_screen_coordinates; +#else + return true; +#endif +} + #if BUILDFLAG(IS_CHROMEOS_ASH) // Returns the aura::Window which stores the window properties for tab-dragging. @@ -1900,8 +1920,12 @@ kMaximizedWindowInset, kMaximizedWindowInset); // Behave as if the |source| was maximized at the start of a drag since this // is consistent with a browser window creation logic in case of windows - // that are as large as the |work_area|. - was_source_maximized_ = true; + // that are as large as the |work_area|. Note: Some platforms do not support + // global screen coordinates tracking, eg: Linux/Wayland, in such cases, + // avoid this heuristic to determine whether the new browser window should + // be maximized or not when completing the drag session. + if (PlatformProvidesAbsoluteWindowPositions()) + was_source_maximized_ = true; } if (source->AsView()->GetWidget()->IsMaximized()) {
diff --git a/chrome/browser/ui/views/tabs/tab_group_views.cc b/chrome/browser/ui/views/tabs/tab_group_views.cc index 677dee0..b231eff 100644 --- a/chrome/browser/ui/views/tabs/tab_group_views.cc +++ b/chrome/browser/ui/views/tabs/tab_group_views.cc
@@ -20,22 +20,23 @@ #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/rect.h" -TabGroupViews::TabGroupViews(TabStrip* tab_strip, +TabGroupViews::TabGroupViews(views::View* container_view, + TabStrip* tab_strip, const tab_groups::TabGroupId& group) - : tab_strip_(tab_strip), group_(group) { - header_ = tab_strip_->AddChildView( + : container_view_(container_view), tab_strip_(tab_strip), group_(group) { + header_ = container_view_->AddChildView( std::make_unique<TabGroupHeader>(tab_strip_, group_)); - underline_ = tab_strip_->AddChildView( + underline_ = container_view_->AddChildView( std::make_unique<TabGroupUnderline>(this, group_)); - highlight_ = tab_strip_->AddChildView( + highlight_ = container_view_->AddChildView( std::make_unique<TabGroupHighlight>(this, group_)); highlight_->SetVisible(false); } TabGroupViews::~TabGroupViews() { - tab_strip_->RemoveChildViewT(std::exchange(header_, nullptr)); - tab_strip_->RemoveChildViewT(std::exchange(underline_, nullptr)); - tab_strip_->RemoveChildViewT(std::exchange(highlight_, nullptr)); + container_view_->RemoveChildViewT(std::exchange(header_, nullptr)); + container_view_->RemoveChildViewT(std::exchange(underline_, nullptr)); + container_view_->RemoveChildViewT(std::exchange(highlight_, nullptr)); } void TabGroupViews::UpdateBounds() {
diff --git a/chrome/browser/ui/views/tabs/tab_group_views.h b/chrome/browser/ui/views/tabs/tab_group_views.h index 6c51b1a..01f9e15 100644 --- a/chrome/browser/ui/views/tabs/tab_group_views.h +++ b/chrome/browser/ui/views/tabs/tab_group_views.h
@@ -9,6 +9,7 @@ #include "components/tab_groups/tab_group_id.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/gfx/geometry/rect.h" +#include "ui/views/view.h" class Tab; class TabGroupHeader; @@ -21,9 +22,11 @@ class TabGroupViews { public: // Creates the various views representing a tab group and adds them to - // |tab_strip| as children. Assumes these views are not destroyed before + // |parent_view| as children. Assumes these views are not destroyed before // |this|. - TabGroupViews(TabStrip* tab_strip, const tab_groups::TabGroupId& group); + TabGroupViews(views::View* container_view, + TabStrip* tab_strip, + const tab_groups::TabGroupId& group); // Destroys the views added during the constructor. ~TabGroupViews(); @@ -59,6 +62,7 @@ SkColor GetGroupBackgroundColor() const; private: + const raw_ptr<views::View> container_view_; const raw_ptr<TabStrip> tab_strip_; const tab_groups::TabGroupId group_; TabGroupHeader* header_;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 11431d75..d9c8c8f 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -985,11 +985,13 @@ // TabStrip, public: TabStrip::TabStrip(std::unique_ptr<TabStripController> controller) - : controller_(std::move(controller)), + : tab_container_(AddChildView(std::make_unique<TabContainer>())), + controller_(std::move(controller)), layout_helper_(std::make_unique<TabStripLayoutHelper>( controller_.get(), base::BindRepeating(&TabStrip::tabs_view_model, base::Unretained(this)))), + bounds_animator_(tab_container_), hover_card_controller_(std::make_unique<TabHoverCardController>(this)), drag_context_(std::make_unique<TabDragContextImpl>(this)) { // TODO(pbos): This is probably incorrect, the background of individual tabs @@ -1027,7 +1029,7 @@ // The child tabs may call back to us from their destructors. Delete them so // that if they call back we aren't in a weird state. - RemoveAllChildViews(); + tab_container_->RemoveAllChildViews(); CHECK(!IsInObserverList()); } @@ -1135,7 +1137,8 @@ Tab* tab = new Tab(this); tab->set_context_menu_controller(&context_menu_controller_); tab->AddObserver(this); - AddChildViewAt(tab, GetViewInsertionIndex(tab, absl::nullopt, model_index)); + tab_container_->AddChildViewAt( + tab, GetViewInsertionIndex(tab, absl::nullopt, model_index)); const bool pinned = data.pinned; tabs_.Add(tab, model_index); selected_tabs_.IncrementFrom(model_index); @@ -1200,7 +1203,7 @@ const bool pinned = data.pinned; moving_tab->SetData(std::move(data)); - ReorderChildView( + tab_container_->ReorderChildView( moving_tab, GetViewInsertionIndex(moving_tab, from_model_index, to_model_index)); @@ -1335,7 +1338,8 @@ } void TabStrip::OnGroupCreated(const tab_groups::TabGroupId& group) { - auto group_view = std::make_unique<TabGroupViews>(this, group); + auto group_view = + std::make_unique<TabGroupViews>(tab_container_, this, group); layout_helper_->InsertGroupHeader(group, group_view->header()); group_views_[group] = std::move(group_view); } @@ -1412,17 +1416,17 @@ TabGroupHeader* group_header = group_views_[group]->header(); const int first_tab = controller_->GetFirstTabInGroup(group).value(); - const int header_index = GetIndexOf(group_header); - const int first_tab_index = GetIndexOf(tab_at(first_tab)); + const int header_index = tab_container_->GetIndexOf(group_header); + const int first_tab_index = tab_container_->GetIndexOf(tab_at(first_tab)); // The header should be just before the first tab. If it isn't, reorder the // header such that it is. Note that the index to reorder to is different // depending on whether the header is before or after the tab, since the // header itself occupies an index. if (header_index < first_tab_index - 1) - ReorderChildView(group_header, first_tab_index - 1); + tab_container_->ReorderChildView(group_header, first_tab_index - 1); if (header_index > first_tab_index - 1) - ReorderChildView(group_header, first_tab_index); + tab_container_->ReorderChildView(group_header, first_tab_index); } void TabStrip::OnGroupClosed(const tab_groups::TabGroupId& group) { @@ -2109,6 +2113,8 @@ SetTabSlotVisibility(); } + tab_container_->SetBounds(0, 0, width(), height()); + if (IsAnimating()) { // Hide tabs that have animated at least partially out of the clip region. SetTabSlotVisibility(); @@ -2151,7 +2157,7 @@ : absl::nullopt; std::vector<ZOrderableTabStripElement> orderable_children; - for (views::View* child : children()) + for (views::View* child : tab_container_->children()) orderable_children.emplace_back(child, dragging_tabs_current_group_underline); @@ -2650,7 +2656,9 @@ // added to the end of the tab strip. In that case we can just return one // beyond the view index of the last existing tab. if (to_model_index >= GetTabCount()) - return (GetTabCount() ? GetIndexOf(tab_at(GetTabCount() - 1)) + 1 : 0); + return (GetTabCount() + ? tab_container_->GetIndexOf(tab_at(GetTabCount() - 1)) + 1 + : 0); // If there is no from_model_index, then the tab is newly added in the middle // of the tab strip. In that case we treat it as coming from the end of the @@ -2663,7 +2671,7 @@ // Since we don't have an absolute mapping from model index to view index, we // anchor on the last known view index at the given to_model_index. Tab* other_tab = tab_at(to_model_index); - int other_view_index = GetIndexOf(other_tab); + int other_view_index = tab_container_->GetIndexOf(other_tab); if (other_view_index <= 0) return 0;
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index 96adbe7..9206d6f 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -24,6 +24,7 @@ #include "chrome/browser/ui/views/frame/browser_root_view.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_animation_state.h" +#include "chrome/browser/ui/views/tabs/tab_container.h" #include "chrome/browser/ui/views/tabs/tab_controller.h" #include "chrome/browser/ui/views/tabs/tab_drag_context.h" #include "chrome/browser/ui/views/tabs/tab_group_header.h" @@ -620,6 +621,9 @@ // in |layout_helper_| until the remove animation completes. views::ViewModelT<Tab> tabs_; + // The View parent for the tabs and the various group views. + TabContainer* tab_container_; + std::map<tab_groups::TabGroupId, std::unique_ptr<TabGroupViews>> group_views_; std::unique_ptr<TabStripController> controller_; @@ -629,7 +633,7 @@ std::unique_ptr<TabStripLayoutHelper> layout_helper_; // Responsible for animating tabs in response to model changes. - views::BoundsAnimator bounds_animator_{this}; + views::BoundsAnimator bounds_animator_; // Responsible for animating the scroll of the tab strip. std::unique_ptr<gfx::LinearAnimation> tab_scrolling_animation_;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc index be70e17..e8cc993 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_strip_unittest.cc
@@ -224,6 +224,14 @@ } } + std::vector<views::View*> GetChildViews() { + // The first (and only) View child of TabStrip is its TabContainer, which + // contains the tabs and group views. + // TODO(1116121): Move tests that test view/focus order to test + // TabContainer directly, once that functionality has been moved there. + return tab_strip_->children()[0]->children(); + } + std::vector<TabGroupViews*> ListGroupViews() const { std::vector<TabGroupViews*> result; for (auto const& group_view_pair : tab_strip_->group_views_) @@ -234,7 +242,7 @@ // Returns all TabSlotViews in the order that they have as ViewChildren of // TabStrip. This should match the actual order that they appear in visually. views::View::Views GetTabSlotViewsInFocusOrder() { - views::View::Views all_children = tab_strip_->children(); + views::View::Views all_children = GetChildViews(); const int num_tab_slot_views = tab_strip_->GetTabCount() + tab_strip_->group_views_.size(); @@ -376,18 +384,18 @@ TestTabStripObserver observer(tab_strip_); controller_->AddTab(0, false); controller_->AddTab(1, false); - const size_t num_children = tab_strip_->children().size(); + const size_t num_children = GetChildViews().size(); EXPECT_EQ(2, tab_strip_->GetTabCount()); controller_->RemoveTab(0); EXPECT_EQ(0, observer.last_tab_removed()); // When removing a tab the tabcount should immediately decrement. EXPECT_EQ(1, tab_strip_->GetTabCount()); // But the number of views should remain the same (it's animatining closed). - EXPECT_EQ(num_children, tab_strip_->children().size()); + EXPECT_EQ(num_children, GetChildViews().size()); CompleteAnimationAndLayout(); - EXPECT_EQ(num_children - 1, tab_strip_->children().size()); + EXPECT_EQ(num_children - 1, GetChildViews().size()); // Remove the last tab to make sure things are cleaned up correctly when // the TabStrip is destroyed and an animation is ongoing.
diff --git a/chrome/browser/ui/views/user_education/browser_feature_promo_controller_unittest.cc b/chrome/browser/ui/views/user_education/browser_feature_promo_controller_unittest.cc index b9d5e32..0f411ee 100644 --- a/chrome/browser/ui/views/user_education/browser_feature_promo_controller_unittest.cc +++ b/chrome/browser/ui/views/user_education/browser_feature_promo_controller_unittest.cc
@@ -38,6 +38,7 @@ #include "components/feature_engagement/test/mock_tracker.h" #include "testing/gmock/include/gmock/gmock.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#include "ui/base/interaction/element_tracker.h" #include "ui/base/l10n/l10n_util.h" #include "ui/events/base_event_utils.h" #include "ui/views/bubble/bubble_border.h" @@ -87,14 +88,14 @@ absl::nullopt, u"Right Click on a Tab and select \"Add Tab To new Group\".", ui::InteractionSequence::StepType::kShown, kTabStripElementId, - std::string(), HelpBubbleArrow::kTopCenter, absl::nullopt); + std::string(), HelpBubbleArrow::kTopCenter); desc.steps.emplace_back(step1); TutorialDescription::Step step2( absl::nullopt, u"Select \"Enter a name for your Tab Group\".", ui::InteractionSequence::StepType::kShown, kTabGroupEditorBubbleId, std::string(), HelpBubbleArrow::kLeftCenter, - false /*must_remain_visible*/); + ui::CustomElementEventType(), false /*must_remain_visible*/); desc.steps.emplace_back(std::move(step2)); user_education_service->tutorial_registry().AddTutorial(
diff --git a/chrome/browser/ui/views/user_education/browser_user_education_service.cc b/chrome/browser/ui/views/user_education/browser_user_education_service.cc index ea08007d..4398b64 100644 --- a/chrome/browser/ui/views/user_education/browser_user_education_service.cc +++ b/chrome/browser/ui/views/user_education/browser_user_education_service.cc
@@ -18,6 +18,7 @@ #include "chrome/grit/generated_resources.h" #include "components/feature_engagement/public/feature_constants.h" #include "components/strings/grit/components_strings.h" +#include "ui/base/interaction/element_tracker.h" #include "ui/base/interaction/interaction_sequence.h" #include "ui/views/interaction/element_tracker_views.h" @@ -184,26 +185,28 @@ absl::nullopt, u"Right Click on a Tab and select \"Add Tab To new Group\".", ui::InteractionSequence::StepType::kShown, kTabStripElementId, - std::string(), HelpBubbleArrow::kTopCenter, absl::nullopt); + std::string(), HelpBubbleArrow::kTopCenter); description.steps.emplace_back(step1); TutorialDescription::Step step2( absl::nullopt, u"Select \"Enter a name for your Tab Group\".", ui::InteractionSequence::StepType::kShown, kTabGroupEditorBubbleId, std::string(), HelpBubbleArrow::kLeftCenter, - false /*must_remain_visible*/); + ui::CustomElementEventType(), + /*must_remain_visible =*/false); description.steps.emplace_back(std::move(step2)); TutorialDescription::Step step3( absl::nullopt, std::u16string(), ui::InteractionSequence::StepType::kHidden, kTabGroupEditorBubbleId, - std::string(), HelpBubbleArrow::kNone, false /*must_remain_visible*/); + std::string(), HelpBubbleArrow::kNone, ui::CustomElementEventType(), + /*must_remain_visible =*/false); description.steps.emplace_back(std::move(step3)); TutorialDescription::Step step4( absl::nullopt, u"Congratulations, you've made your first tab group.", ui::InteractionSequence::StepType::kShown, kTabGroupHeaderElementId, - std::string(), HelpBubbleArrow::kTopCenter, absl::nullopt); + std::string(), HelpBubbleArrow::kTopCenter); description.steps.emplace_back(std::move(step4)); tutorial_registry.AddTutorial(kTabGroupTutorialId, std::move(description));
diff --git a/chrome/browser/ui/views/user_education/tutorial_interactive_uitest.cc b/chrome/browser/ui/views/user_education/tutorial_interactive_uitest.cc new file mode 100644 index 0000000..23d7d393 --- /dev/null +++ b/chrome/browser/ui/views/user_education/tutorial_interactive_uitest.cc
@@ -0,0 +1,107 @@ +// Copyright 2022 The Chromium 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/bind.h" +#include "base/callback_helpers.h" +#include "base/test/bind.h" +#include "base/test/mock_callback.h" +#include "chrome/app/chrome_command_ids.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/browser_element_identifiers.h" +#include "chrome/browser/ui/browser_window.h" +#include "chrome/browser/ui/user_education/feature_promo_controller.h" +#include "chrome/browser/ui/user_education/tutorial/tutorial_registry.h" +#include "chrome/browser/ui/user_education/tutorial/tutorial_service.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" +#include "ui/base/interaction/element_identifier.h" +#include "ui/base/interaction/element_tracker.h" +#include "ui/base/interaction/expect_call_in_scope.h" +#include "ui/base/interaction/interaction_sequence.h" +#include "ui/events/base_event_utils.h" +#include "ui/events/event.h" +#include "ui/views/controls/button/button.h" +#include "ui/views/interaction/element_tracker_views.h" + +namespace { +constexpr char kTestTutorialId[] = "TutorialInteractiveUitest Tutorial"; +DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kCustomEventType1); +} // namespace + +class TutorialInteractiveUitest : public InProcessBrowserTest { + public: + void SetUpOnMainThread() override { + GetTutorialService()->tutorial_registry()->AddTutorial( + kTestTutorialId, GetDefaultTutorialDescription()); + } + + void TearDownOnMainThread() override { + auto* const service = GetTutorialService(); + service->SetOnCompleteTutorialForTesting(base::DoNothing()); + service->SetOnAbortTutorialForTesting(base::DoNothing()); + service->AbortTutorial(); + service->tutorial_registry()->RemoveTutorialForTesting(kTestTutorialId); + } + + protected: + TutorialService* GetTutorialService() { + return static_cast<FeaturePromoControllerCommon*>( + browser()->window()->GetFeaturePromoController()) + ->tutorial_service_for_testing(); + } + + views::View* GetView(ui::ElementIdentifier id) { + return views::ElementTrackerViews::GetInstance()->GetFirstMatchingView( + id, browser()->window()->GetElementContext()); + } + + TutorialDescription GetDefaultTutorialDescription() { + TutorialDescription description; + TutorialDescription::Step step1(absl::nullopt, u"Here's the app menu.", + ui::InteractionSequence::StepType::kShown, + kAppMenuButtonElementId, std::string(), + HelpBubbleArrow::kTopRight); + description.steps.emplace_back(step1); + + TutorialDescription::Step step2( + absl::nullopt, u"A thing happened. Now click the app menu.", + ui::InteractionSequence::StepType::kCustomEvent, + ui::ElementIdentifier(), std::string(), HelpBubbleArrow::kTopCenter, + kCustomEventType1); + description.steps.emplace_back(step2); + + TutorialDescription::Step step3( + absl::nullopt, u"App menu clicked! Congratulations!", + ui::InteractionSequence::StepType::kActivated, kAppMenuButtonElementId, + std::string(), HelpBubbleArrow::kTopRight); + description.steps.emplace_back(step3); + + return description; + } +}; + +IN_PROC_BROWSER_TEST_F(TutorialInteractiveUitest, SampleTutorial) { + UNCALLED_MOCK_CALLBACK(TutorialService::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(TutorialService::AbortedCallback, aborted); + + GetTutorialService()->SetOnCompleteTutorialForTesting(completed.Get()); + GetTutorialService()->SetOnAbortTutorialForTesting(aborted.Get()); + + const bool started = GetTutorialService()->StartTutorial( + kTestTutorialId, browser()->window()->GetElementContext()); + EXPECT_TRUE(started); + + views::ElementTrackerViews::GetInstance()->NotifyCustomEvent( + kCustomEventType1, GetView(kTabStripElementId)); + + EXPECT_CALL_IN_SCOPE(completed, Run, { + // Simulate app menu button press. + auto* const button = + static_cast<views::Button*>(GetView(kAppMenuButtonElementId)); + button->OnKeyPressed(ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_SPACE, + ui::EF_NONE, ui::EventTimeForNow())); + button->OnKeyReleased(ui::KeyEvent(ui::ET_KEY_RELEASED, ui::VKEY_SPACE, + ui::EF_NONE, ui::EventTimeForNow())); + }); +}
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc index 9b25d9b..08bf7f2 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_browsertest.cc
@@ -24,6 +24,15 @@ helper_.NavigateBrowser("SiteA"); helper_.CheckLaunchIconShown(); } + +#if BUILDFLAG(IS_WIN) +IN_PROC_BROWSER_TEST_F(WebAppIntegrationBrowserTest, UninstallFromOS) { + helper_.InstallCreateShortcutWindowed("SiteA"); + helper_.UninstallFromOS("SiteA"); + helper_.CheckAppNotInList("SiteA"); +} +#endif + // Automated tests: // TODO(crbug.com/1279704): Test is consistently failing on Mac and Win7.
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc index cf811ad..d0a1cf1f 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.cc
@@ -105,6 +105,8 @@ #if BUILDFLAG(IS_WIN) #include <codecvt> #include "base/win/shortcut.h" +#include "chrome/browser/browser_process.h" +#include "chrome/browser/ui/startup/startup_browser_creator.h" #include "chrome/common/chrome_switches.h" #endif @@ -1000,6 +1002,34 @@ AfterStateChangeAction(); } +void WebAppIntegrationTestDriver::UninstallFromOS( + const std::string& site_mode) { +#if BUILDFLAG(IS_WIN) + BeforeStateChangeAction(); + absl::optional<AppState> app_state = GetAppBySiteMode( + before_state_change_action_state_.get(), profile(), site_mode); + ASSERT_TRUE(app_state.has_value()) + << "No app installed for site: " << site_mode; + auto app_id = app_state->id; + WebAppTestUninstallObserver observer(profile()); + observer.BeginListening({app_id}); + + // Trigger app uninstall via command line. + extensions::ScopedTestDialogAutoConfirm auto_confirm( + extensions::ScopedTestDialogAutoConfirm::ACCEPT); + base::CommandLine command_line(base::CommandLine::NO_PROGRAM); + command_line.AppendSwitchASCII(switches::kUninstallAppId, app_id); + StartupBrowserCreator::ProcessCommandLineAlreadyRunning( + command_line, {}, + {profile()->GetPath(), StartupProfileMode::kBrowserWindow}); + + observer.Wait(); + AfterStateChangeAction(); +#else + NOTREACHED() << "Not supported on non-Windows platforms"; +#endif +} + void WebAppIntegrationTestDriver::CheckAppListEmpty() { BeforeStateCheckAction(); absl::optional<ProfileState> state =
diff --git a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h index de62fb8..e222b106 100644 --- a/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h +++ b/chrome/browser/ui/views/web_apps/web_app_integration_test_driver.h
@@ -177,6 +177,7 @@ void UninstallFromList(const std::string& site_mode); void UninstallFromMenu(const std::string& site_mode); void UninstallPolicyApp(const std::string& site_mode); + void UninstallFromOS(const std::string& site_mode); // State Check Actions: void CheckAppListEmpty();
diff --git a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc index 1b09875..b118d9d 100644 --- a/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc +++ b/chrome/browser/ui/web_applications/web_app_ui_manager_impl.cc
@@ -216,21 +216,24 @@ bool WebAppUiManagerImpl::UninstallAndReplaceIfExists( const std::vector<AppId>& from_apps, const AppId& to_app) { - bool has_migrated = false; + bool has_migrated_ui = false; bool uninstall_triggered = false; for (const AppId& from_app : from_apps) { if (!IsAppInstalled(profile_, from_app)) continue; - if (!has_migrated) { + if (!has_migrated_ui) { + has_migrated_ui = true; #if BUILDFLAG(IS_CHROMEOS_ASH) // Grid position in app list. auto* app_list_syncable_service = app_list::AppListSyncableServiceFactory::GetForProfile(profile_); - if (app_list_syncable_service->GetSyncItem(from_app)) { + bool to_app_in_shelf = + app_list_syncable_service->GetPinPosition(to_app).IsValid(); + // If the new app is already pinned to the shelf don't transfer UI prefs + // across as that could cause it to become unpinned. + if (!to_app_in_shelf) app_list_syncable_service->TransferItemAttributes(from_app, to_app); - has_migrated = true; - } #endif // If migration of user/UI data is required for other app types consider @@ -252,7 +255,6 @@ to_app, GetExtensionDisplayMode(profile_, from_extension), /*is_user_action=*/false); - has_migrated = true; auto shortcut_info = web_app::ShortcutInfoForExtensionAndProfile( from_extension, profile_); auto callback = @@ -263,7 +265,7 @@ uninstall_triggered = true; continue; } - has_migrated = true; + // The from_app could be a web app. os_integration_manager_->GetShortcutInfoForApp( from_app,
diff --git a/chrome/browser/ui/webui/chrome_untrusted_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_untrusted_web_ui_controller_factory.cc index 196a935..8c8f206 100644 --- a/chrome/browser/ui/webui/chrome_untrusted_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_untrusted_web_ui_controller_factory.cc
@@ -23,6 +23,8 @@ #if BUILDFLAG(IS_ANDROID) #include "chrome/browser/ui/webui/video_tutorials/video_player_ui.h" +#else +#include "chrome/browser/ui/webui/feed/feed_ui_config.h" #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -32,6 +34,7 @@ #include "ash/webui/help_app_ui/help_app_kids_magazine_untrusted_ui.h" #include "ash/webui/os_feedback_ui/os_feedback_untrusted_ui.h" #include "ash/webui/personalization_app/untrusted_personalization_app_ui_config.h" +#include "chrome/browser/ash/web_applications/camera_app/camera_app_untrusted_ui_config.h" #include "chrome/browser/ash/web_applications/crosh_ui.h" #include "chrome/browser/ash/web_applications/help_app/help_app_untrusted_ui_config.h" #include "chrome/browser/ash/web_applications/media_app/media_app_guest_ui_config.h" @@ -69,6 +72,8 @@ #if BUILDFLAG(IS_ANDROID) register_config(std::make_unique<video_tutorials::VideoPlayerUIConfig>()); +#else + register_config(std::make_unique<feed::FeedUIConfig>()); #endif // BUILDFLAG(IS_ANDROID) #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -78,6 +83,7 @@ register_config(std::make_unique<MediaAppGuestUIConfig>()); register_config(std::make_unique<ash::UntrustedPersonalizationAppUIConfig>()); register_config(std::make_unique<ash::HelpAppUntrustedUIConfig>()); + register_config(std::make_unique<ash::CameraAppUntrustedUIConfig>()); register_config( std::make_unique<ash::HelpAppKidsMagazineUntrustedUIConfig>()); if (ash::features::IsProjectorEnabled()) @@ -96,7 +102,6 @@ register_config(std::make_unique<ash::UntrustedSampleSystemWebAppUIConfig>()); #endif // !defined(OFFICIAL_BUILD) #endif // BUILDFLAG(IS_CHROMEOS_ASH) - return config_list; }
diff --git a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc index ffa6d1b..8f59c57c 100644 --- a/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc +++ b/chrome/browser/ui/webui/chrome_web_ui_controller_factory.cc
@@ -992,8 +992,7 @@ return &NewWebUI<chromeos::ArcPowerControlUI>; } } - if (url.host_piece() == chrome::kChromeUIEmojiPickerHost && - base::FeatureList::IsEnabled(chromeos::features::kImeSystemEmojiPicker)) { + if (url.host_piece() == chrome::kChromeUIEmojiPickerHost) { return &NewWebUI<chromeos::EmojiUI>; } if (url.host_piece() == ash::eche_app::kChromeUIEcheAppHost &&
diff --git a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc index f2d8713..73f987b8 100644 --- a/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc +++ b/chrome/browser/ui/webui/chromeos/crostini_upgrader/crostini_upgrader_ui.cc
@@ -47,10 +47,12 @@ {"promptTitle", IDS_CROSTINI_UPGRADER_TITLE}, {"backingUpTitle", IDS_CROSTINI_UPGRADER_BACKING_UP_TITLE}, + {"backupErrorTitle", IDS_CROSTINI_UPGRADER_BACKUP_ERROR_TITLE}, {"backupSucceededTitle", IDS_CROSTINI_UPGRADER_BACKUP_SUCCEEDED_TITLE}, {"prechecksFailedTitle", IDS_CROSTINI_UPGRADER_PRECHECKS_FAILED_TITLE}, {"upgradingTitle", IDS_CROSTINI_UPGRADER_UPGRADING_TITLE}, {"restoreTitle", IDS_CROSTINI_UPGRADER_RESTORE_TITLE}, + {"restoreErrorTitle", IDS_CROSTINI_UPGRADER_RESTORE_ERROR_TITLE}, {"restoreSucceededTitle", IDS_CROSTINI_UPGRADER_RESTORE_SUCCEEDED_TITLE}, {"succeededTitle", IDS_CROSTINI_UPGRADER_SUCCEEDED_TITLE}, {"cancelingTitle", IDS_CROSTINI_UPGRADER_CANCELING_TITLE}, @@ -61,6 +63,7 @@ {"promptMessage", IDS_CROSTINI_UPGRADER_BODY}, {"backingUpMessage", IDS_CROSTINI_UPGRADER_BACKING_UP_MESSAGE}, + {"backupErrorMessage", IDS_CROSTINI_UPGRADER_BACKUP_ERROR_MESSAGE}, {"backupSucceededMessage", IDS_CROSTINI_UPGRADER_BACKUP_SUCCEEDED_MESSAGE}, {"upgradingMessage", IDS_CROSTINI_UPGRADER_UPGRADING}, @@ -68,6 +71,7 @@ {"cancelingMessage", IDS_CROSTINI_UPGRADER_CANCELING}, {"offerRestoreMessage", IDS_CROSTINI_UPGRADER_OFFER_RESTORE_MESSAGE}, {"restoreMessage", IDS_CROSTINI_UPGRADER_RESTORE_MESSAGE}, + {"restoreErrorMessage", IDS_CROSTINI_UPGRADER_RESTORE_ERROR_MESSAGE}, {"restoreSucceededMessage", IDS_CROSTINI_UPGRADER_RESTORE_SUCCEEDED_MESSAGE}, {"logFileMessageError", IDS_CROSTINI_UPGRADER_LOG_FILE_ERROR},
diff --git a/chrome/browser/ui/webui/extensions/extensions_ui.cc b/chrome/browser/ui/webui/extensions/extensions_ui.cc index 3c142fc..8d222821 100644 --- a/chrome/browser/ui/webui/extensions/extensions_ui.cc +++ b/chrome/browser/ui/webui/extensions/extensions_ui.cc
@@ -231,6 +231,7 @@ {"missingOrUninstalledExtension", IDS_MISSING_OR_UNINSTALLED_EXTENSION}, {"noActivities", IDS_EXTENSIONS_NO_ACTIVITIES}, {"noErrorsToShow", IDS_EXTENSIONS_ERROR_NO_ERRORS_CODE_MESSAGE}, + {"removeSitesDialogTitle", IDS_EXTENSIONS_REMOVE_SITES_DIALOG_TITLE}, {"runtimeHostsDialogInputError", IDS_EXTENSIONS_RUNTIME_HOSTS_DIALOG_INPUT_ERROR}, {"runtimeHostsDialogInputLabel",
diff --git a/chrome/browser/ui/webui/feed/OWNERS b/chrome/browser/ui/webui/feed/OWNERS new file mode 100644 index 0000000..4a7fc50 --- /dev/null +++ b/chrome/browser/ui/webui/feed/OWNERS
@@ -0,0 +1 @@ +file://components/feed/OWNERS
diff --git a/chrome/browser/ui/webui/feed/feed_ui.cc b/chrome/browser/ui/webui/feed/feed_ui.cc new file mode 100644 index 0000000..976578e --- /dev/null +++ b/chrome/browser/ui/webui/feed/feed_ui.cc
@@ -0,0 +1,55 @@ +// Copyright 2022 The Chromium 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/webui/feed/feed_ui.h" +#include "base/containers/span.h" +#include "chrome/browser/ui/webui/webui_util.h" +#include "chrome/grit/feed_resources.h" +#include "chrome/grit/feed_resources_map.h" +#include "components/feed/feed_feature_list.h" +#include "content/public/browser/web_contents.h" +#include "content/public/browser/web_ui.h" +#include "content/public/browser/web_ui_data_source.h" +#include "content/public/common/url_constants.h" +#include "ui/base/resource/resource_bundle.h" +#include "ui/base/webui/resource_path.h" + +namespace feed { + +FeedUI::FeedUI(content::WebUI* web_ui) : ui::UntrustedWebUIController(web_ui) { + web_ui->AddRequestableScheme("https"); + // TODO(crbug.com/1292623): We should disable http requests before launching. + web_ui->AddRequestableScheme("http"); + + // Create a URLDataSource and add resources. + auto* source = content::WebUIDataSource::Create("chrome-untrusted://feed/"); + webui::SetupWebUIDataSource( + source, base::make_span(kFeedResources, kFeedResourcesSize), + IDR_FEED_FEED_HTML); + + // TODO(crbug.com/1292623): CSP is weak during development and will be + // tightened once the final architecture is decided. + // - Unsafe-eval/unsafe-inline is used by wasm code and is likely that we can + // avoid this for the final production version. + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::ScriptSrc, + "script-src chrome-untrusted://resources 'unsafe-eval' 'unsafe-inline' " + "https://*.google.com https://google.com http://localhost:8000 'self';"); + + // We want to be able to load frames from Google. + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::FrameSrc, + "frame-src https://google.com https://*.google.com 'self';"); + source->OverrideContentSecurityPolicy( + network::mojom::CSPDirectiveName::DefaultSrc, "default-src 'self';"); + + // Configurable javascript for prototyping purposes. + source->AddString("scriptUrl", feed::kWebUiScriptFetchUrl.Get()); + + // Register the URLDataSource + auto* browser_context = web_ui->GetWebContents()->GetBrowserContext(); + content::WebUIDataSource::Add(browser_context, source); +} + +} // namespace feed
diff --git a/chrome/browser/ui/webui/feed/feed_ui.h b/chrome/browser/ui/webui/feed/feed_ui.h new file mode 100644 index 0000000..79b5fcc --- /dev/null +++ b/chrome/browser/ui/webui/feed/feed_ui.h
@@ -0,0 +1,23 @@ +// Copyright 2022 The Chromium 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_WEBUI_FEED_FEED_UI_H_ +#define CHROME_BROWSER_UI_WEBUI_FEED_FEED_UI_H_ + +#include "ui/webui/untrusted_web_ui_controller.h" + +namespace feed { + +class FeedUI : public ui::UntrustedWebUIController { + public: + explicit FeedUI(content::WebUI* web_ui); + + FeedUI(const FeedUI&) = delete; + FeedUI& operator=(const FeedUI&) = delete; + ~FeedUI() override = default; +}; + +} // namespace feed + +#endif // CHROME_BROWSER_UI_WEBUI_FEED_FEED_UI_H_
diff --git a/chrome/browser/ui/webui/feed/feed_ui_config.cc b/chrome/browser/ui/webui/feed/feed_ui_config.cc new file mode 100644 index 0000000..9a97d3b --- /dev/null +++ b/chrome/browser/ui/webui/feed/feed_ui_config.cc
@@ -0,0 +1,28 @@ +// Copyright 2022 The Chromium 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/webui/feed/feed_ui_config.h" +#include "chrome/browser/ui/webui/feed/feed_ui.h" +#include "components/feed/feed_feature_list.h" + +namespace { +const char kFeedHost[] = "feed"; +} + +namespace feed { + +FeedUIConfig::FeedUIConfig() + // Set scheme and host. + : WebUIConfig(content::kChromeUIUntrustedScheme, kFeedHost) {} + +std::unique_ptr<content::WebUIController> FeedUIConfig::CreateWebUIController( + content::WebUI* web_ui) { + return std::make_unique<FeedUI>(web_ui); +} + +bool FeedUIConfig::IsWebUIEnabled(content::BrowserContext* browser_context) { + return base::FeatureList::IsEnabled(feed::kWebUiFeed); +} + +} // namespace feed
diff --git a/chrome/browser/ui/webui/feed/feed_ui_config.h b/chrome/browser/ui/webui/feed/feed_ui_config.h new file mode 100644 index 0000000..b362f81 --- /dev/null +++ b/chrome/browser/ui/webui/feed/feed_ui_config.h
@@ -0,0 +1,25 @@ +// Copyright 2022 The Chromium 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_WEBUI_FEED_FEED_UI_CONFIG_H_ +#define CHROME_BROWSER_UI_WEBUI_FEED_FEED_UI_CONFIG_H_ + +#include "content/public/common/url_constants.h" +#include "ui/webui/webui_config.h" + +namespace feed { + +class FeedUIConfig : public ui::WebUIConfig { + public: + FeedUIConfig(); + ~FeedUIConfig() override = default; + + std::unique_ptr<content::WebUIController> CreateWebUIController( + content::WebUI* web_ui) override; + + bool IsWebUIEnabled(content::BrowserContext* browser_context) override; +}; + +} // namespace feed +#endif // CHROME_BROWSER_UI_WEBUI_FEED_FEED_UI_CONFIG_H_
diff --git a/chrome/browser/ui/webui/history/foreign_session_handler.cc b/chrome/browser/ui/webui/history/foreign_session_handler.cc index 37a417a..66a7b27 100644 --- a/chrome/browser/ui/webui/history/foreign_session_handler.cc +++ b/chrome/browser/ui/webui/history/foreign_session_handler.cc
@@ -312,8 +312,7 @@ DictionaryPrefUpdate pref_update(Profile::FromWebUI(web_ui())->GetPrefs(), prefs::kNtpCollapsedForeignSessions); base::Value* current_collapsed_sessions = pref_update.Get(); - std::unique_ptr<base::Value> collapsed_sessions( - current_collapsed_sessions->CreateDeepCopy()); + base::Value collapsed_sessions = current_collapsed_sessions->Clone(); current_collapsed_sessions->DictClear(); // Note: we don't own the SyncedSessions themselves. @@ -333,7 +332,7 @@ FormatSessionTime(session->modified_time)); session_data.SetDoubleKey("timestamp", session->modified_time.ToJsTime()); - bool is_collapsed = collapsed_sessions->FindKey(session_tag); + bool is_collapsed = collapsed_sessions.FindKey(session_tag); session_data.SetBoolKey("collapsed", is_collapsed); if (is_collapsed) current_collapsed_sessions->SetBoolKey(session_tag, true);
diff --git a/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.cc b/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.cc index 3a65d93..efe1078 100644 --- a/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.cc
@@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/values.h" +#include "chrome/browser/ash/quick_pair/fast_pair_support_utils.h" #include "chromeos/network/network_event_log.h" #include "content/public/browser/web_ui.h" #include "device/bluetooth/bluetooth_adapter_factory.h" @@ -14,6 +15,8 @@ namespace { const char kIsDeviceBlockedByPolicy[] = "isDeviceBlockedByPolicy"; +const char kRequestFastPairDeviceSupport[] = + "requestFastPairDeviceSupportStatus"; } // namespace @@ -32,6 +35,10 @@ kIsDeviceBlockedByPolicy, base::BindRepeating(&BluetoothHandler::HandleIsDeviceBlockedByPolicy, base::Unretained(this))); + web_ui()->RegisterMessageCallback( + kRequestFastPairDeviceSupport, + base::BindRepeating(&BluetoothHandler::HandleRequestFastPairDeviceSupport, + base::Unretained(this))); } void BluetoothHandler::OnJavascriptAllowed() {} @@ -68,5 +75,14 @@ base::Value(device->IsBlockedByPolicy())); } +void BluetoothHandler::HandleRequestFastPairDeviceSupport( + base::Value::ConstListView args) { + AllowJavascript(); + + base::Value is_supported( + ash::quick_pair::IsFastPairSupported(bluetooth_adapter_)); + FireWebUIListener("fast-pair-device-supported-status", is_supported); +} + } // namespace settings } // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h b/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h index d535110..f9443f3 100644 --- a/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h +++ b/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler.h
@@ -33,6 +33,7 @@ scoped_refptr<device::BluetoothAdapter> adapter); void HandleIsDeviceBlockedByPolicy(base::Value::ConstListView args); + void HandleRequestFastPairDeviceSupport(base::Value::ConstListView args); scoped_refptr<device::BluetoothAdapter> bluetooth_adapter_; base::WeakPtrFactory<BluetoothHandler> weak_ptr_factory_{this};
diff --git a/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler_unittest.cc index 33faac6..b92a01f 100644 --- a/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/bluetooth_handler_unittest.cc
@@ -91,5 +91,23 @@ EXPECT_TRUE(call_data.arg3()->GetBool()); } +TEST_F(BluetoothHandlerTest, GetRequestFastPairDeviceSupport) { + mock_device_->SetIsBlockedByPolicy(true); + + size_t call_data_count_before_call = test_web_ui()->call_data().size(); + + base::Value args(base::Value::Type::LIST); + test_web_ui()->HandleReceivedMessage("requestFastPairDeviceSupportStatus", + &base::Value::AsListValue(args)); + + ASSERT_EQ(call_data_count_before_call + 1u, + test_web_ui()->call_data().size()); + const content::TestWebUI::CallData& call_data = + CallDataAtIndex(call_data_count_before_call); + EXPECT_EQ("cr.webUIListenerCallback", call_data.function_name()); + EXPECT_EQ("fast-pair-device-supported-status", call_data.arg1()->GetString()); + EXPECT_FALSE(call_data.arg2()->GetBool()); +} + } // namespace settings } // namespace chromeos
diff --git a/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc b/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc index 935fd97..0b66c9f 100644 --- a/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/bluetooth_section.cc
@@ -197,6 +197,12 @@ IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CASE_BATTERY_PERCENTAGE_A11Y_LABEL}, {"bluetoothDeviceDetailRightBudBatteryPercentageA11yLabel", IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_RIGHT_BUD_BATTERY_PERCENTAGE_A11Y_LABEL}, + {"bluetoothTrueWirelessLeftBudLabel", + IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_LEFT_BUD_LABEL}, + {"bluetoothTrueWirelessCaseLabel", + IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_CASE_LABEL}, + {"bluetoothTrueWirelessRightBudLabel", + IDS_SETTINGS_BLUETOOTH_TRUE_WIRELESS_RIGHT_BUD_LABEL}, {"bluetoothDeviceDetailConnectionFailureLabel", IDS_SETTINGS_BLUETOOTH_DEVICE_DETAIL_CONNECTION_FAILURE_LABEL}, {"bluetoothDeviceDetailDisconnectedA11yLabel",
diff --git a/chrome/browser/ui/webui/settings/chromeos/languages_section.cc b/chrome/browser/ui/webui/settings/chromeos/languages_section.cc index bf10945f..943f7d3 100644 --- a/chrome/browser/ui/webui/settings/chromeos/languages_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/languages_section.cc
@@ -447,9 +447,6 @@ AddLanguagesPageStringsV2(html_source); AddInputPageStringsV2(html_source); - html_source->AddBoolean("imeOptionsInSettings", - base::FeatureList::IsEnabled( - ::chromeos::features::kImeOptionsInSettings)); html_source->AddBoolean("enableLanguageSettingsV2Update2", IsLanguageSettingsV2Update2Enabled()); html_source->AddBoolean("onDeviceGrammarCheckEnabled",
diff --git a/chrome/browser/ui/webui/settings/chromeos/main_section.cc b/chrome/browser/ui/webui/settings/chromeos/main_section.cc index dcad6f45..a2e2488 100644 --- a/chrome/browser/ui/webui/settings/chromeos/main_section.cc +++ b/chrome/browser/ui/webui/settings/chromeos/main_section.cc
@@ -163,10 +163,6 @@ user_manager::UserManager::Get()->IsLoggedInAsAnyKioskApp()); html_source->AddBoolean("isChildAccount", profile()->IsChild()); - html_source->AddBoolean( - "appManagementIntentSettingsEnabled", - base::FeatureList::IsEnabled(::features::kAppManagementIntentSettings)); - html_source->AddBoolean("isPersonalizationHubEnabled", ash::features::IsPersonalizationHubEnabled());
diff --git a/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc b/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc index 4fe4c389..a0aba8e 100644 --- a/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/metrics_reporting_handler_unittest.cc
@@ -45,7 +45,7 @@ base::ListValue args; args.Append(std::make_unique<base::Value>(1)); - handler()->HandleGetMetricsReporting(args.GetList()); + handler()->HandleGetMetricsReporting(args.GetListDeprecated()); EXPECT_TRUE(handler()->IsJavascriptAllowed()); EXPECT_EQ(1u, test_web_ui()->call_data().size());
diff --git a/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc b/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc index 3b9a901..55a18176 100644 --- a/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc +++ b/chrome/browser/ui/webui/settings/site_settings_helper_unittest.cc
@@ -102,18 +102,17 @@ /*incognito=*/false, &exceptions); // |exceptions| size should be 2. One blocked and one embargoed origins. - ASSERT_EQ(2U, exceptions.GetListDeprecated().size()); - base::Value* value = nullptr; + const auto& list = exceptions.GetListDeprecated(); + ASSERT_EQ(2U, list.size()); + // Get last added origin. - exceptions.Get(0, &value); - base::Value* is_embargoed = value->FindKey(site_settings::kIsEmbargoed); + base::Value* is_embargoed = list[0].FindKey(site_settings::kIsEmbargoed); ASSERT_NE(nullptr, is_embargoed); // Last added origin is blocked, |embargo| key should be false. EXPECT_FALSE(is_embargoed->GetBool()); // Get embargoed origin. - exceptions.Get(1, &value); - is_embargoed = value->FindKey(site_settings::kIsEmbargoed); + is_embargoed = list[1].FindKey(site_settings::kIsEmbargoed); ASSERT_NE(nullptr, is_embargoed); EXPECT_TRUE(is_embargoed->GetBool()); }
diff --git a/chrome/browser/web_applications/adjustments/BUILD.gn b/chrome/browser/web_applications/adjustments/BUILD.gn index 2458c3c..b0d9cc5 100644 --- a/chrome/browser/web_applications/adjustments/BUILD.gn +++ b/chrome/browser/web_applications/adjustments/BUILD.gn
@@ -8,6 +8,8 @@ sources = [ "link_capturing_pref_migration.cc", "link_capturing_pref_migration.h", + "preinstalled_web_app_duplication_fixer.cc", + "preinstalled_web_app_duplication_fixer.h", "web_app_adjustments.cc", "web_app_adjustments.h", ] @@ -28,13 +30,19 @@ testonly = true sources = [] + if (is_chromeos_ash) { sources += [ "link_capturing_pref_migration_browsertest.cc" ] } + if (!is_chromeos_lacros) { + sources += [ "preinstalled_web_app_duplication_fixer_browsertest.cc" ] + } + defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ] deps = [ + ":adjustments", "//chrome/browser/web_applications", "//chrome/browser/web_applications:web_applications_test_support_minimal", "//chrome/test:test_support",
diff --git a/chrome/browser/web_applications/adjustments/preinstalled_web_app_duplication_fixer.cc b/chrome/browser/web_applications/adjustments/preinstalled_web_app_duplication_fixer.cc new file mode 100644 index 0000000..0fdd337 --- /dev/null +++ b/chrome/browser/web_applications/adjustments/preinstalled_web_app_duplication_fixer.cc
@@ -0,0 +1,104 @@ +// Copyright 2022 The Chromium 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/adjustments/preinstalled_web_app_duplication_fixer.h" + +#include "base/metrics/histogram_functions.h" +#include "base/task/post_task.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/externally_installed_web_app_prefs.h" +#include "chrome/browser/web_applications/preinstalled_app_install_features.h" +#include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h" +#include "chrome/browser/web_applications/web_app.h" +#include "chrome/browser/web_applications/web_app_provider.h" +#include "chrome/browser/web_applications/web_app_registrar.h" +#include "components/services/app_service/public/cpp/types_util.h" + +namespace web_app { + +namespace { +bool g_skip_startup_for_testing = false; +} + +const char + PreinstalledWebAppDuplicationFixer::kHistogramAppDuplicationFixApplied[] = + "WebApp.Preinstalled.AppDuplicationFixApplied"; + +void PreinstalledWebAppDuplicationFixer::SkipStartupForTesting() { + g_skip_startup_for_testing = true; +} + +PreinstalledWebAppDuplicationFixer::PreinstalledWebAppDuplicationFixer( + Profile& profile) + : profile_(profile) { + if (g_skip_startup_for_testing) + return; + // WebAppAdjustmentsFactory guarantees that AppServiceProxy exists. + apps::AppRegistryCache& app_registry_cache = + apps::AppServiceProxyFactory::GetForProfile(&profile_) + ->AppRegistryCache(); + if (app_registry_cache.IsAppTypeInitialized( + apps::mojom::AppType::kChromeApp)) { + ScanForDuplication(); + } else { + // Await OnAppTypeInitialized(). + scoped_observation_.Observe(&app_registry_cache); + } +} + +PreinstalledWebAppDuplicationFixer::~PreinstalledWebAppDuplicationFixer() = + default; + +void PreinstalledWebAppDuplicationFixer::OnAppUpdate( + const apps::AppUpdate& update) {} + +void PreinstalledWebAppDuplicationFixer::OnAppTypeInitialized( + apps::mojom::AppType app_type) { + if (app_type != apps::mojom::AppType::kChromeApp) + return; + + ScanForDuplication(); + scoped_observation_.Reset(); +} + +void PreinstalledWebAppDuplicationFixer::OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) { + scoped_observation_.Reset(); +} + +void PreinstalledWebAppDuplicationFixer::ScanForDuplicationForTesting() { + ScanForDuplication(); +} + +void PreinstalledWebAppDuplicationFixer::ScanForDuplication() { + std::vector<PreinstalledWebAppMigration> migrations = + GetPreinstalledWebAppMigrations(profile_); + size_t fix_count = 0; + apps::AppServiceProxyFactory::GetForProfile(&profile_) + ->AppRegistryCache() + .ForEachApp( + [this, &migrations, &fix_count](const apps::AppUpdate& update) { + if (update.AppType() != apps::mojom::AppType::kChromeApp) + return; + + if (update.Readiness() != apps::mojom::Readiness::kReady) + return; + + for (const PreinstalledWebAppMigration& migration : migrations) { + if (update.AppId() != migration.old_chrome_app_id) + continue; + // Remove evidence of web app installation causing + // PreinstalledWebAppManager::Synchronize() to reinstall the web + // app and re-trigger migration. + fix_count += ExternallyInstalledWebAppPrefs(profile_.GetPrefs()) + .Remove(migration.install_url); + } + }); + + base::UmaHistogramCounts100(kHistogramAppDuplicationFixApplied, fix_count); +} + +} // namespace web_app
diff --git a/chrome/browser/web_applications/adjustments/preinstalled_web_app_duplication_fixer.h b/chrome/browser/web_applications/adjustments/preinstalled_web_app_duplication_fixer.h new file mode 100644 index 0000000..740b579 --- /dev/null +++ b/chrome/browser/web_applications/adjustments/preinstalled_web_app_duplication_fixer.h
@@ -0,0 +1,54 @@ +// Copyright 2022 The Chromium 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_ADJUSTMENTS_PREINSTALLED_WEB_APP_DUPLICATION_FIXER_H_ +#define CHROME_BROWSER_WEB_APPLICATIONS_ADJUSTMENTS_PREINSTALLED_WEB_APP_DUPLICATION_FIXER_H_ + +#include "base/memory/weak_ptr.h" +#include "base/scoped_observation.h" +#include "components/services/app_service/public/cpp/app_registry_cache.h" + +class Profile; + +namespace apps { +class AppUpdate; +namespace mojom { +enum class AppType; +} +} // namespace apps + +namespace web_app { + +class PreinstalledWebAppDuplicationFixer + : public apps::AppRegistryCache::Observer { + public: + static const char kHistogramAppDuplicationFixApplied[]; + static void SkipStartupForTesting(); + + explicit PreinstalledWebAppDuplicationFixer(Profile& profile); + ~PreinstalledWebAppDuplicationFixer() override; + + // apps::AppRegistryCache::Observer: + void OnAppUpdate(const apps::AppUpdate& update) override; + void OnAppTypeInitialized(apps::mojom::AppType app_type) override; + void OnAppRegistryCacheWillBeDestroyed( + apps::AppRegistryCache* cache) override; + + void ScanForDuplicationForTesting(); + + private: + void ObserveAppRegistryCache(); + + void ScanForDuplication(); + + Profile& profile_; + + base::ScopedObservation<apps::AppRegistryCache, + apps::AppRegistryCache::Observer> + scoped_observation_{this}; +}; + +} // namespace web_app + +#endif // CHROME_BROWSER_WEB_APPLICATIONS_ADJUSTMENTS_PREINSTALLED_WEB_APP_DUPLICATION_FIXER_H_
diff --git a/chrome/browser/web_applications/adjustments/preinstalled_web_app_duplication_fixer_browsertest.cc b/chrome/browser/web_applications/adjustments/preinstalled_web_app_duplication_fixer_browsertest.cc new file mode 100644 index 0000000..c15aa49 --- /dev/null +++ b/chrome/browser/web_applications/adjustments/preinstalled_web_app_duplication_fixer_browsertest.cc
@@ -0,0 +1,310 @@ +// Copyright 2022 The Chromium 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/adjustments/preinstalled_web_app_duplication_fixer.h" + +#include "base/strings/string_piece.h" +#include "base/test/bind.h" +#include "base/test/metrics/histogram_tester.h" +#include "chrome/browser/extensions/extension_browsertest.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/web_applications/adjustments/web_app_adjustments.h" +#include "chrome/browser/web_applications/externally_installed_web_app_prefs.h" +#include "chrome/browser/web_applications/os_integration_manager.h" +#include "chrome/browser/web_applications/preinstalled_web_app_manager.h" +#include "chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h" +#include "chrome/browser/web_applications/test/web_app_install_test_utils.h" +#include "chrome/browser/web_applications/web_app.h" +#include "chrome/browser/web_applications/web_app_helpers.h" +#include "chrome/browser/web_applications/web_app_provider.h" +#include "chrome/common/chrome_features.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" +#include "extensions/browser/test_extension_registry_observer.h" +#include "url/gurl.h" + +#if BUILDFLAG(IS_CHROMEOS_ASH) +// #include "ash/public/cpp/shelf_model.h" +#include "chrome/browser/ui/app_list/app_list_syncable_service.h" +#include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + +namespace web_app { + +class PreinstalledWebAppDuplicationFixerBrowserTest + : public extensions::ExtensionBrowserTest { + public: + static GURL install_url() { + return GURL("https://www.example.com/install_url"); + } + static GURL start_url() { return GURL("https://www.example.com/start_url"); } + static AppId web_app_id() { + return GenerateAppId(absl::nullopt, start_url()); + } + static extensions::ExtensionId chrome_app_id() { + return "kbmnembihfiondgfjekmnmcbddelicoi"; + } + + PreinstalledWebAppDuplicationFixerBrowserTest() { + PreinstalledWebAppManager::SkipStartupForTesting(); + PreinstalledWebAppDuplicationFixer::SkipStartupForTesting(); + } + ~PreinstalledWebAppDuplicationFixerBrowserTest() override = default; + + // InProcessBrowserTest: + void SetUpOnMainThread() override { + extensions::ExtensionBrowserTest::SetUpOnMainThread(); + + provider_ = WebAppProvider::GetForTest(browser()->profile()); + InProcessBrowserTest::SetUpOnMainThread(); + web_app::test::WaitUntilReady(provider_); + + ExternalInstallOptions options(install_url(), DisplayMode::kStandalone, + ExternalInstallSource::kExternalDefault); + options.user_type_allowlist = {"unmanaged"}; + options.uninstall_and_replace = {chrome_app_id()}; + options.only_use_app_info_factory = true; + options.app_info_factory = base::BindRepeating( + [](GURL start_url) { + auto info = std::make_unique<WebAppInstallInfo>(); + info->title = u"Test app"; + info->start_url = start_url; + return info; + }, + start_url()); + options.expected_app_id = web_app_id(); + preinstalled_app_data_.apps = {options}; + } + + void SyncPreinstalledWebApps() { + base::RunLoop run_loop; + provider_->preinstalled_web_app_manager().LoadAndSynchronizeForTesting( + base::BindLambdaForTesting( + [&](std::map<GURL, ExternallyManagedAppManager::InstallResult> + install_results, + std::map<GURL, bool> uninstall_results) { run_loop.Quit(); })); + run_loop.Run(); + } + + void SyncPreinstalledWebAppsAwaitChromeAppUninstall() { + extensions::TestExtensionRegistryObserver uninstall_observer( + extensions::ExtensionRegistry::Get(profile())); + SyncPreinstalledWebApps(); + ASSERT_EQ(uninstall_observer.WaitForExtensionUninstalled()->id(), + chrome_app_id()); + } + + bool IsWebAppInstalled() const { + return provider_->registrar().IsInstalled(web_app_id()); + } + + bool IsWebAppExternalInstallPrefSet() { + return ExternallyInstalledWebAppPrefs(profile()->GetPrefs()) + .LookupAppId(install_url()) == web_app_id(); + } + + bool IsWebAppInSync() const { + return provider_->registrar() + .GetAppById(web_app_id()) + ->GetSources() + .test(Source::kSync); + } + + void UninstallWebApp() { test::UninstallWebApp(profile(), web_app_id()); } + + void RunAppDuplicationFix() { + WebAppAdjustments::Get(profile()) + ->preinstalled_web_app_duplication_fixer() + ->ScanForDuplicationForTesting(); + } + + std::vector<base::Bucket> GetFixCountMetrics() { + return histogram_tester_.GetAllSamples( + PreinstalledWebAppDuplicationFixer::kHistogramAppDuplicationFixApplied); + } + + void InstallChromeApp() { + const extensions::Extension* extension = + InstallExtension(test_data_dir_.AppendASCII("hosted_app.crx"), 1); + ASSERT_EQ(extension->id(), chrome_app_id()); + } + + bool IsChromeAppInstalled() { + return extensions::ExtensionRegistry::Get(profile()) + ->enabled_extensions() + .Contains(chrome_app_id()); + } + +#if BUILDFLAG(IS_CHROMEOS_ASH) + void PinApp(const std::string& app_id) { + auto* service = + app_list::AppListSyncableServiceFactory::GetForProfile(profile()); + service->SetPinPosition(app_id, service->GetLastPosition()); + } + + bool IsAppPinned(const std::string& app_id) { + return app_list::AppListSyncableServiceFactory::GetForProfile(profile()) + ->GetPinPosition(app_id) + .IsValid(); + } +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + + protected: + WebAppProvider* provider_; + base::test::ScopedFeatureList feature_list_{ + features::kPreinstalledWebAppDuplicationFixer}; + ScopedTestingPreinstalledAppData preinstalled_app_data_; + base::HistogramTester histogram_tester_; + OsIntegrationManager::ScopedSuppressForTesting os_hooks_supress_; +}; + +IN_PROC_BROWSER_TEST_F(PreinstalledWebAppDuplicationFixerBrowserTest, + FixDuplicateChromeApp) { + SyncPreinstalledWebApps(); + EXPECT_TRUE(IsWebAppInstalled()); + EXPECT_FALSE(IsChromeAppInstalled()); + EXPECT_TRUE(IsWebAppExternalInstallPrefSet()); + + // Running the fix while the Chrome app is not installed should do nothing. + { + RunAppDuplicationFix(); + EXPECT_TRUE(IsWebAppInstalled()); + EXPECT_FALSE(IsChromeAppInstalled()); + EXPECT_EQ(GetFixCountMetrics(), (std::vector<base::Bucket>{{0, 1}})); + EXPECT_TRUE(IsWebAppExternalInstallPrefSet()); + } + + InstallChromeApp(); + EXPECT_TRUE(IsChromeAppInstalled()); + + // Resyncing preinstalled web app configs again will not re-migrate the web + // app despite the Chrome app being installed. + { + SyncPreinstalledWebApps(); + EXPECT_TRUE(IsWebAppInstalled()); + EXPECT_TRUE(IsChromeAppInstalled()); + } + + // Running the fix causes the Chrome app to get migrated on the next + // preinstalled web app sync. + { + RunAppDuplicationFix(); + EXPECT_TRUE(IsWebAppInstalled()); + EXPECT_TRUE(IsChromeAppInstalled()); + EXPECT_EQ(GetFixCountMetrics(), + (std::vector<base::Bucket>{{0, 1}, {1, 1}})); + EXPECT_FALSE(IsWebAppExternalInstallPrefSet()); + + SyncPreinstalledWebAppsAwaitChromeAppUninstall(); + EXPECT_TRUE(IsWebAppInstalled()); + EXPECT_FALSE(IsChromeAppInstalled()); + } +} + +IN_PROC_BROWSER_TEST_F(PreinstalledWebAppDuplicationFixerBrowserTest, + RemigrateUninstalledWebApp) { + SyncPreinstalledWebApps(); + InstallChromeApp(); + EXPECT_TRUE(IsWebAppInstalled()); + EXPECT_TRUE(IsChromeAppInstalled()); + EXPECT_TRUE(IsWebAppExternalInstallPrefSet()); + + UninstallWebApp(); + EXPECT_FALSE(IsWebAppInstalled()); + EXPECT_TRUE(IsChromeAppInstalled()); + EXPECT_TRUE(IsWebAppExternalInstallPrefSet()); + + RunAppDuplicationFix(); + EXPECT_FALSE(IsWebAppInstalled()); + EXPECT_TRUE(IsChromeAppInstalled()); + EXPECT_EQ(GetFixCountMetrics(), (std::vector<base::Bucket>{{1, 1}})); + EXPECT_FALSE(IsWebAppExternalInstallPrefSet()); + + // Running the preinstalled web app sync should remigrate the old Chrome app + // even if the user had uninstalled the web app. + { + SyncPreinstalledWebAppsAwaitChromeAppUninstall(); + EXPECT_TRUE(IsWebAppInstalled()); + EXPECT_FALSE(IsChromeAppInstalled()); + } +} + +IN_PROC_BROWSER_TEST_F(PreinstalledWebAppDuplicationFixerBrowserTest, + RunFixOnSyncInstalledWebApp) { + SyncPreinstalledWebApps(); + InstallChromeApp(); + EXPECT_TRUE(IsWebAppInstalled()); + EXPECT_TRUE(IsChromeAppInstalled()); + EXPECT_TRUE(IsWebAppExternalInstallPrefSet()); + + // Simulate a user install of the same web app to put it in sync. + { + auto info = std::make_unique<WebAppInstallInfo>(); + info->start_url = start_url(); + AppId app_id = test::InstallWebApp(profile(), std::move(info)); + ASSERT_EQ(app_id, web_app_id()); + ASSERT_TRUE(IsWebAppInSync()); + } + + // The duplication fix should have no effect on the sync install status of the + // web app. + { + RunAppDuplicationFix(); + ASSERT_TRUE(IsWebAppInSync()); + } +} + +#if BUILDFLAG(IS_CHROMEOS_ASH) +IN_PROC_BROWSER_TEST_F(PreinstalledWebAppDuplicationFixerBrowserTest, + WebAppPinnedChromeAppUnpinned) { + SyncPreinstalledWebApps(); + InstallChromeApp(); + + PinApp(web_app_id()); + EXPECT_TRUE(IsAppPinned(web_app_id())); + EXPECT_FALSE(IsAppPinned(chrome_app_id())); + + RunAppDuplicationFix(); + SyncPreinstalledWebAppsAwaitChromeAppUninstall(); + + // If the web app already exists and is pinned it should not take on the + // Chrome app's unpinned UI position. + EXPECT_TRUE(IsAppPinned(web_app_id())); +} + +IN_PROC_BROWSER_TEST_F(PreinstalledWebAppDuplicationFixerBrowserTest, + WebAppUnpinnedChromeAppPinned) { + SyncPreinstalledWebApps(); + InstallChromeApp(); + + PinApp(chrome_app_id()); + EXPECT_FALSE(IsAppPinned(web_app_id())); + EXPECT_TRUE(IsAppPinned(chrome_app_id())); + + RunAppDuplicationFix(); + SyncPreinstalledWebAppsAwaitChromeAppUninstall(); + + // If the web app already exists and is not pinned it should take on the + // Chrome app's pinned UI position. + EXPECT_TRUE(IsAppPinned(web_app_id())); +} + +IN_PROC_BROWSER_TEST_F(PreinstalledWebAppDuplicationFixerBrowserTest, + BothUnpinned) { + SyncPreinstalledWebApps(); + InstallChromeApp(); + + EXPECT_FALSE(IsAppPinned(web_app_id())); + EXPECT_FALSE(IsAppPinned(chrome_app_id())); + + RunAppDuplicationFix(); + SyncPreinstalledWebAppsAwaitChromeAppUninstall(); + + // If neither app was pinned the web app should remain unpinned. + EXPECT_FALSE(IsAppPinned(web_app_id())); +} +#endif // BUILDFLAG(IS_CHROMEOS_ASH) + +} // namespace web_app
diff --git a/chrome/browser/web_applications/adjustments/web_app_adjustments.cc b/chrome/browser/web_applications/adjustments/web_app_adjustments.cc index aeea093b..6c91dc9 100644 --- a/chrome/browser/web_applications/adjustments/web_app_adjustments.cc +++ b/chrome/browser/web_applications/adjustments/web_app_adjustments.cc
@@ -10,6 +10,7 @@ #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_provider_factory.h" #include "chrome/browser/web_applications/web_app_utils.h" +#include "chrome/common/chrome_features.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" namespace web_app { @@ -18,11 +19,23 @@ // WebAppAdjustments implementation // -------------------------------- +WebAppAdjustments* WebAppAdjustments::Get(Profile* profile) { + return static_cast<WebAppAdjustments*>( + WebAppAdjustmentsFactory::GetInstance()->GetServiceForBrowserContext( + profile, /*create=*/false)); +} + WebAppAdjustments::WebAppAdjustments(Profile* profile) { #if BUILDFLAG(IS_CHROMEOS) link_capturing_pref_migration_ = std::make_unique<web_app::LinkCapturingPrefMigration>(*profile); #endif // BUILDFLAG(IS_CHROMEOS) + + if (base::FeatureList::IsEnabled( + features::kPreinstalledWebAppDuplicationFixer)) { + preinstalled_web_app_duplication_fixer_ = + std::make_unique<PreinstalledWebAppDuplicationFixer>(*profile); + } } WebAppAdjustments::~WebAppAdjustments() = default;
diff --git a/chrome/browser/web_applications/adjustments/web_app_adjustments.h b/chrome/browser/web_applications/adjustments/web_app_adjustments.h index 491e393..8864843f 100644 --- a/chrome/browser/web_applications/adjustments/web_app_adjustments.h +++ b/chrome/browser/web_applications/adjustments/web_app_adjustments.h
@@ -8,6 +8,7 @@ #include <memory> #include "chrome/browser/web_applications/adjustments/link_capturing_pref_migration.h" +#include "chrome/browser/web_applications/adjustments/preinstalled_web_app_duplication_fixer.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "components/keyed_service/core/keyed_service.h" @@ -24,12 +25,22 @@ // Everything in here should have a removal date. class WebAppAdjustments : public KeyedService { public: + static WebAppAdjustments* Get(Profile* profile); + explicit WebAppAdjustments(Profile* profile); ~WebAppAdjustments() override; + PreinstalledWebAppDuplicationFixer* preinstalled_web_app_duplication_fixer() { + return preinstalled_web_app_duplication_fixer_.get(); + } + private: // TODO(crbug.com/1262906): This was added in M97, remove in M107. std::unique_ptr<LinkCapturingPrefMigration> link_capturing_pref_migration_; + + // TODO(crbug.com/1290716): This was added in M100, remove in M120. + std::unique_ptr<PreinstalledWebAppDuplicationFixer> + preinstalled_web_app_duplication_fixer_; }; class WebAppAdjustmentsFactory : public BrowserContextKeyedServiceFactory { @@ -40,6 +51,8 @@ static WebAppAdjustmentsFactory* GetInstance(); private: + friend class WebAppAdjustments; + // BrowserContextKeyedServiceFactory: KeyedService* BuildServiceInstanceFor( content::BrowserContext* context) const override;
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc index 7daa3b8b..2a311d1 100644 --- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc +++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.cc
@@ -479,8 +479,7 @@ } #if !BUILDFLAG(IS_CHROMEOS_LACROS) -std::unique_ptr<apps::App> WebAppPublisherHelper::CreateWebApp( - const WebApp* web_app) { +apps::AppPtr WebAppPublisherHelper::CreateWebApp(const WebApp* web_app) { apps::Readiness readiness = web_app->is_locally_installed() ? (web_app->is_uninstalling() ? apps::Readiness::kUninstalledByUser @@ -492,7 +491,7 @@ readiness = apps::Readiness::kDisabledByPolicy; #endif - std::unique_ptr<apps::App> app = apps::AppPublisher::MakeApp( + auto app = apps::AppPublisher::MakeApp( apps::ConvertMojomAppTypToAppType(app_type()), web_app->app_id(), readiness, web_app->name(), apps::ConvertMojomInstallReasonToInstallReason(
diff --git a/chrome/browser/web_applications/app_service/web_app_publisher_helper.h b/chrome/browser/web_applications/app_service/web_app_publisher_helper.h index 5fa78a27..2216de5 100644 --- a/chrome/browser/web_applications/app_service/web_app_publisher_helper.h +++ b/chrome/browser/web_applications/app_service/web_app_publisher_helper.h
@@ -133,8 +133,8 @@ apps::Permissions CreatePermissions(const WebApp* web_app); #if !BUILDFLAG(IS_CHROMEOS_LACROS) - // Creates an |std::unique_ptr<apps::App>| describing |web_app|. - std::unique_ptr<apps::App> CreateWebApp(const WebApp* web_app); + // Creates an |apps::AppPtr| describing |web_app|. + apps::AppPtr CreateWebApp(const WebApp* web_app); #endif // Creates an |apps::mojom::App| describing |web_app|.
diff --git a/chrome/browser/web_applications/app_service/web_apps.cc b/chrome/browser/web_applications/app_service/web_apps.cc index ef8d07ec..8c06c5e7 100644 --- a/chrome/browser/web_applications/app_service/web_apps.cc +++ b/chrome/browser/web_applications/app_service/web_apps.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/web_applications/web_app_provider.h" #include "chrome/browser/web_applications/web_app_registrar.h" #include "chrome/browser/web_applications/web_app_utils.h" -#include "chrome/common/chrome_features.h" #include "components/content_settings/core/common/content_settings.h" #include "components/content_settings/core/common/content_settings_pattern.h" #include "components/content_settings/core/common/content_settings_types.h" @@ -243,7 +242,7 @@ return; } - std::vector<std::unique_ptr<apps::App>> apps; + std::vector<apps::AppPtr> apps; for (apps::mojom::AppPtr& app : mojom_apps) { apps.push_back(apps::ConvertMojomAppToApp(app)); } @@ -291,10 +290,10 @@ std::move(accessing_microphone)); } -std::vector<std::unique_ptr<apps::App>> WebApps::CreateWebApps() { +std::vector<apps::AppPtr> WebApps::CreateWebApps() { DCHECK(provider_); - std::vector<std::unique_ptr<apps::App>> apps; + std::vector<apps::AppPtr> apps; for (const WebApp& web_app : provider_->registrar().GetApps()) { if (Accepts(web_app.app_id())) { apps.push_back(publisher_helper().CreateWebApp(&web_app)); @@ -319,7 +318,7 @@ void WebApps::InitWebApps() { RegisterPublisher(apps::ConvertMojomAppTypToAppType(app_type_)); - std::vector<std::unique_ptr<apps::App>> apps = CreateWebApps(); + std::vector<apps::AppPtr> apps = CreateWebApps(); if (apps.empty()) { return; } @@ -438,9 +437,7 @@ } // Read shortcuts menu item icons from disk, if any. - if (base::FeatureList::IsEnabled( - features::kDesktopPWAsAppIconShortcutsMenuUI) && - !web_app->shortcuts_menu_item_infos().empty()) { + if (!web_app->shortcuts_menu_item_infos().empty()) { provider()->icon_manager().ReadAllShortcutsMenuIcons( app_id, base::BindOnce(&WebApps::OnShortcutsMenuIconsRead, base::AsWeakPtr<WebApps>(this), app_id,
diff --git a/chrome/browser/web_applications/app_service/web_apps.h b/chrome/browser/web_applications/app_service/web_apps.h index 53bf2270..84d3b6f 100644 --- a/chrome/browser/web_applications/app_service/web_apps.h +++ b/chrome/browser/web_applications/app_service/web_apps.h
@@ -18,6 +18,7 @@ #include "chrome/browser/web_applications/app_service/web_app_publisher_helper.h" #include "chrome/browser/web_applications/web_app_id.h" #include "chrome/browser/web_applications/web_app_install_info.h" +#include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/icon_types.h" #include "components/services/app_service/public/cpp/publisher_base.h" #include "components/services/app_service/public/mojom/app_service.mojom.h" @@ -134,7 +135,7 @@ absl::optional<bool> accessing_camera, absl::optional<bool> accessing_microphone) override; - std::vector<std::unique_ptr<apps::App>> CreateWebApps(); + std::vector<apps::AppPtr> CreateWebApps(); void ConvertWebApps(std::vector<apps::mojom::AppPtr>* apps_out); void InitWebApps(); void StartPublishingWebApps(
diff --git a/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc b/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc index 972f3165f..7fa9ace2 100644 --- a/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc +++ b/chrome/browser/web_applications/app_service/web_apps_chromeos_browsertest.cc
@@ -11,14 +11,12 @@ #include "ash/public/cpp/shelf_model.h" #include "base/run_loop.h" #include "base/test/bind.h" -#include "base/test/scoped_feature_list.h" #include "chrome/browser/apps/app_service/app_service_proxy.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/ui/ash/shelf/chrome_shelf_controller_util.h" #include "chrome/browser/ui/web_applications/test/web_app_browsertest_util.h" #include "chrome/browser/ui/web_applications/web_app_controller_browsertest.h" #include "chrome/browser/web_applications/web_app_id.h" -#include "chrome/common/chrome_features.h" #include "chrome/test/base/ui_test_utils.h" #include "content/public/browser/notification_service.h" #include "content/public/test/browser_test.h" @@ -60,17 +58,7 @@ } // namespace -class WebAppsChromeOsBrowserTest : public web_app::WebAppControllerBrowserTest { - public: - WebAppsChromeOsBrowserTest() { - feature_list_.InitWithFeatures( - {features::kDesktopPWAsAppIconShortcutsMenuUI}, {}); - } - ~WebAppsChromeOsBrowserTest() override = default; - - private: - base::test::ScopedFeatureList feature_list_; -}; +using WebAppsChromeOsBrowserTest = web_app::WebAppControllerBrowserTest; IN_PROC_BROWSER_TEST_F(WebAppsChromeOsBrowserTest, ShortcutIcons) { const GURL app_url =
diff --git a/chrome/browser/web_applications/externally_installed_web_app_prefs.cc b/chrome/browser/web_applications/externally_installed_web_app_prefs.cc index af7c04a..41080349 100644 --- a/chrome/browser/web_applications/externally_installed_web_app_prefs.cc +++ b/chrome/browser/web_applications/externally_installed_web_app_prefs.cc
@@ -168,6 +168,11 @@ update->SetKey(url.spec(), std::move(dict)); } +bool ExternallyInstalledWebAppPrefs::Remove(const GURL& url) { + DictionaryPrefUpdate update(pref_service_, prefs::kWebAppsExtensionIDs); + return update->RemoveKey(url.spec()); +} + absl::optional<AppId> ExternallyInstalledWebAppPrefs::LookupAppId( const GURL& url) const { DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
diff --git a/chrome/browser/web_applications/externally_installed_web_app_prefs.h b/chrome/browser/web_applications/externally_installed_web_app_prefs.h index a870780..8142a93 100644 --- a/chrome/browser/web_applications/externally_installed_web_app_prefs.h +++ b/chrome/browser/web_applications/externally_installed_web_app_prefs.h
@@ -56,6 +56,7 @@ void Insert(const GURL& url, const AppId& app_id, ExternalInstallSource install_source); + bool Remove(const GURL& url); absl::optional<AppId> LookupAppId(const GURL& url) const; bool HasNoApps() const;
diff --git a/chrome/browser/web_applications/preinstalled_app_install_features.cc b/chrome/browser/web_applications/preinstalled_app_install_features.cc index 5bae94a..199fb59 100644 --- a/chrome/browser/web_applications/preinstalled_app_install_features.cc +++ b/chrome/browser/web_applications/preinstalled_app_install_features.cc
@@ -95,6 +95,7 @@ // See |kAllowDefaultWebAppMigrationForChromeOsManagedUsers| comment above. if (base::FeatureList::IsEnabled(*feature) && feature->name == feature_name && IsMigrationFeature(*feature) && + profile.GetProfilePolicyConnector() && profile.GetProfilePolicyConnector()->IsManaged()) { return base::FeatureList::IsEnabled( kAllowDefaultWebAppMigrationForChromeOsManagedUsers);
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc index 0a3b3872..7b99a8c2 100644 --- a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc +++ b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.cc
@@ -9,6 +9,7 @@ #include "build/branding_buildflags.h" #include "build/build_config.h" #include "build/buildflag.h" +#include "chrome/browser/web_applications/preinstalled_app_install_features.h" #include "chrome/browser/web_applications/web_app_constants.h" #include "chrome/common/chrome_switches.h" @@ -96,76 +97,72 @@ PreinstalledWebAppMigration&&) = default; PreinstalledWebAppMigration::~PreinstalledWebAppMigration() = default; -const std::vector<PreinstalledWebAppMigration>& -GetPreinstalledWebAppMigrations() { - static base::NoDestructor<std::vector<PreinstalledWebAppMigration>> - preinstalled_web_app_migrations([] { - std::vector<PreinstalledWebAppMigration> migrations; - for (const ExternalInstallOptions& options : GetPreinstalledWebApps()) { - if (!options.expected_app_id || - options.uninstall_and_replace.size() != 1) { - continue; - } +std::vector<PreinstalledWebAppMigration> GetPreinstalledWebAppMigrations( + Profile& profile) { + std::vector<PreinstalledWebAppMigration> migrations; + for (const ExternalInstallOptions& options : GetPreinstalledWebApps()) { + if (!options.expected_app_id) + continue; - PreinstalledWebAppMigration migration; - migration.install_url = options.install_url; - migration.expected_web_app_id = *options.expected_app_id; - migration.old_chrome_app_id = options.uninstall_and_replace[0]; - migration.gate_on_feature = options.gate_on_feature; - migrations.push_back(std::move(migration)); - } + // All entries in the default web app migration had only one Chrome app to + // replace. + if (options.uninstall_and_replace.size() != 1) + continue; + + if (options.gate_on_feature && !IsPreinstalledAppInstallFeatureEnabled( + *options.gate_on_feature, profile)) { + continue; + } + + PreinstalledWebAppMigration migration; + migration.install_url = options.install_url; + migration.expected_web_app_id = *options.expected_app_id; + migration.old_chrome_app_id = options.uninstall_and_replace[0]; + migrations.push_back(std::move(migration)); + } #if BUILDFLAG(GOOGLE_CHROME_BRANDING) && BUILDFLAG(IS_CHROMEOS) - // Manually hard coded entries from - // https://chrome-internal.googlesource.com/chromeos/overlays/chromeos-overlay/+/main/chromeos-base/chromeos-default-apps/files/web_apps - // for any json configs that include a uninstall_and_replace field. - // This is a temporary measure while the default web app duplication - // issue is cleaned up. - // TODO(crbug.com/1290716): Clean up once no longer needed. - { - PreinstalledWebAppMigration migration; - migration.install_url = GURL( - "https://play.google.com/books/installwebapp?usp=chromedefault"); - migration.expected_web_app_id = kPlayBooksAppId; - migration.old_chrome_app_id = extension_misc::kGooglePlayBooksAppId; - migration.gate_on_feature = - kMigrateDefaultChromeAppToWebAppsNonGSuite.name; - migrations.push_back(std::move(migration)); - } - { - PreinstalledWebAppMigration migration; - migration.install_url = - GURL("https://keep.google.com/installwebapp?usp=chrome_default"); - migration.expected_web_app_id = kGoogleKeepAppId; - migration.old_chrome_app_id = extension_misc::kGoogleKeepAppId; - migration.gate_on_feature = - kMigrateDefaultChromeAppToWebAppsGSuite.name; - migrations.push_back(std::move(migration)); - } - { - PreinstalledWebAppMigration migration; - migration.install_url = - GURL("https://www.google.com/maps/preview/pwa/ttinstall.html"); - migration.expected_web_app_id = kGoogleMapsAppId; - migration.old_chrome_app_id = extension_misc::kGoogleMapsAppId; - migration.gate_on_feature = - kMigrateDefaultChromeAppToWebAppsNonGSuite.name; - migrations.push_back(std::move(migration)); - } - { - PreinstalledWebAppMigration migration; - migration.install_url = GURL( - "https://play.google.com/store/movies/" - "installwebapp?usp=chrome_default"); - migration.expected_web_app_id = kGoogleMoviesAppId; - migration.old_chrome_app_id = extension_misc::kGooglePlayMoviesAppId; - migration.gate_on_feature = - kMigrateDefaultChromeAppToWebAppsNonGSuite.name; - migrations.push_back(std::move(migration)); - } + // Manually hard coded entries from + // https://chrome-internal.googlesource.com/chromeos/overlays/chromeos-overlay/+/main/chromeos-base/chromeos-default-apps/files/web_apps + // for any json configs that include a uninstall_and_replace field. + // This is a temporary measure while the default web app duplication + // issue is cleaned up. + // TODO(crbug.com/1290716): Clean up once no longer needed. + if (IsPreinstalledAppInstallFeatureEnabled( + kMigrateDefaultChromeAppToWebAppsGSuite.name, profile)) { + PreinstalledWebAppMigration keep_migration; + keep_migration.install_url = + GURL("https://keep.google.com/installwebapp?usp=chrome_default"); + keep_migration.expected_web_app_id = kGoogleKeepAppId; + keep_migration.old_chrome_app_id = extension_misc::kGoogleKeepAppId; + migrations.push_back(std::move(keep_migration)); + } + + if (IsPreinstalledAppInstallFeatureEnabled( + kMigrateDefaultChromeAppToWebAppsNonGSuite.name, profile)) { + PreinstalledWebAppMigration books_migration; + books_migration.install_url = + GURL("https://play.google.com/books/installwebapp?usp=chromedefault"); + books_migration.expected_web_app_id = kPlayBooksAppId; + books_migration.old_chrome_app_id = extension_misc::kGooglePlayBooksAppId; + migrations.push_back(std::move(books_migration)); + + PreinstalledWebAppMigration maps_migration; + maps_migration.install_url = + GURL("https://www.google.com/maps/preview/pwa/ttinstall.html"); + maps_migration.expected_web_app_id = kGoogleMapsAppId; + maps_migration.old_chrome_app_id = extension_misc::kGoogleMapsAppId; + migrations.push_back(std::move(maps_migration)); + + PreinstalledWebAppMigration movies_migration; + movies_migration.install_url = GURL( + "https://play.google.com/store/movies/" + "installwebapp?usp=chrome_default"); + movies_migration.expected_web_app_id = kGoogleMoviesAppId; + movies_migration.old_chrome_app_id = extension_misc::kGooglePlayMoviesAppId; + migrations.push_back(std::move(movies_migration)); + } #endif // BUILDFLAG(GOOGLE_CHROME_BRANDING) && BUILDFLAG(IS_CHROMEOS) - return migrations; - }()); - return *preinstalled_web_app_migrations; + return migrations; } } // namespace web_app
diff --git a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h index fb9ad43..2261ff8 100644 --- a/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h +++ b/chrome/browser/web_applications/preinstalled_web_apps/preinstalled_web_apps.h
@@ -7,7 +7,11 @@ #include <vector> +#include "base/containers/flat_set.h" #include "chrome/browser/web_applications/external_install_options.h" +#include "url/gurl.h" + +class Profile; namespace web_app { @@ -23,13 +27,12 @@ GURL install_url; AppId expected_web_app_id; AppId old_chrome_app_id; - absl::optional<std::string> gate_on_feature; }; // Returns the list of preinstalled web apps that are migrations away from their // corresponding Chrome app. -const std::vector<PreinstalledWebAppMigration>& -GetPreinstalledWebAppMigrations(); +std::vector<PreinstalledWebAppMigration> GetPreinstalledWebAppMigrations( + Profile& profile); // A scoped helper to provide a testing set of preinstalled app data. This will // replace the default set.
diff --git a/chrome/browser/web_applications/test/web_app_test_utils.cc b/chrome/browser/web_applications/test/web_app_test_utils.cc index 0e234437..d21a337 100644 --- a/chrome/browser/web_applications/test/web_app_test_utils.cc +++ b/chrome/browser/web_applications/test/web_app_test_utils.cc
@@ -19,6 +19,7 @@ #include "chrome/browser/web_applications/web_app_install_info.h" #include "chrome/browser/web_applications/web_app_utils.h" #include "components/services/app_service/public/cpp/url_handler_info.h" +#include "components/webapps/browser/installable/installable_metrics.h" #include "content/public/browser/service_worker_context.h" #include "content/public/browser/storage_partition.h" #include "third_party/blink/public/common/manifest/manifest.h" @@ -472,6 +473,11 @@ if (random.next_bool()) app->SetPermissionsPolicy(CreateRandomPermissionsPolicy(random)); + uint32_t install_source = + random.next_uint(static_cast<int>(webapps::WebappInstallSource::COUNT)); + app->SetInstallSourceForMetrics( + static_cast<webapps::WebappInstallSource>(install_source)); + // `random` should not be used after the chromeos block if the result // is expected to be deterministic across cros and non-cros builds. if (IsChromeOsDataMandatory()) {
diff --git a/chrome/browser/web_applications/web_app_unittest.cc b/chrome/browser/web_applications/web_app_unittest.cc index 13231595..a30a26f2 100644 --- a/chrome/browser/web_applications/web_app_unittest.cc +++ b/chrome/browser/web_applications/web_app_unittest.cc
@@ -376,7 +376,7 @@ } ], "handle_links": "kAuto", "install_time": "1970-01-10 21:57:36.131 UTC", - "install_source_for_metrics": "not set", + "install_source_for_metrics": 13, "is_from_sync_and_pending_installation": false, "is_generated_icon": true, "is_locally_installed": false,
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt index 784acc7..7025f14 100644 --- a/chrome/build/linux.pgo.txt +++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@ -chrome-linux-main-1644235013-9a39b207e703942ce691ce65bc33f9f55a7e7bdf.profdata +chrome-linux-main-1644278354-9ae50f60d57fd69399c52f9b2b6c222b7fb5b746.profdata
diff --git a/chrome/build/mac-arm.pgo.txt b/chrome/build/mac-arm.pgo.txt index 938ef2a4..17dca1e 100644 --- a/chrome/build/mac-arm.pgo.txt +++ b/chrome/build/mac-arm.pgo.txt
@@ -1 +1 @@ -chrome-mac-arm-main-1644256741-0816098113694915125f480b9e5f7d5f6b749885.profdata +chrome-mac-arm-main-1644299677-56526546328bc5f49bdead547eb03209f650f87c.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt index b22938da..f0bd55f 100644 --- a/chrome/build/mac.pgo.txt +++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@ -chrome-mac-main-1644235013-6abcb405ac3857ad2bfdd63b083364c4526f075c.profdata +chrome-mac-main-1644299677-9b4eb9a73e7215a9994816b78e1621f425c5b009.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt index 58b36cf..1a68885 100644 --- a/chrome/build/win32.pgo.txt +++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@ -chrome-win32-main-1644245945-315f95094e9ba53f32315729394d36338db7c937.profdata +chrome-win32-main-1644299677-4fab251a77fee37e1a16e98463c10ff8fa154055.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt index 4caf24b..1a10c7d 100644 --- a/chrome/build/win64.pgo.txt +++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@ -chrome-win64-main-1644235013-2c0069b7e80fdc733d8ac19e79468f4c13a4d760.profdata +chrome-win64-main-1644299677-0a50801ba745fb838de18008b7aa0bdfc75e6fb1.profdata
diff --git a/chrome/chrome_paks.gni b/chrome/chrome_paks.gni index 0320dc9..afa0bf9 100644 --- a/chrome/chrome_paks.gni +++ b/chrome/chrome_paks.gni
@@ -146,6 +146,7 @@ "$root_gen_dir/chrome/dev_ui_resources.pak", "$root_gen_dir/chrome/download_shelf_resources.pak", "$root_gen_dir/chrome/downloads_resources.pak", + "$root_gen_dir/chrome/feed_resources.pak", "$root_gen_dir/chrome/feedback_resources.pak", "$root_gen_dir/chrome/gaia_auth_host_resources.pak", "$root_gen_dir/chrome/history_resources.pak", @@ -174,6 +175,7 @@ "//chrome/browser/resources/commander:resources", "//chrome/browser/resources/download_shelf:resources", "//chrome/browser/resources/downloads:resources", + "//chrome/browser/resources/feed:resources", "//chrome/browser/resources/feedback_webui:resources", "//chrome/browser/resources/gaia_auth_host:resources", "//chrome/browser/resources/history:resources",
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 9af3cbc..cb934d2 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -68,13 +68,6 @@ base::FEATURE_DISABLED_BY_DEFAULT}; #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) -// Controls whether intent settings are available in App Management. -// TODO(crbug/1226925): Do not enable flag unless this has been resolved. -const base::Feature kAppManagementIntentSettings{ - "AppManagementIntentSettings", base::FEATURE_ENABLED_BY_DEFAULT}; -#endif // BUILDFLAG(IS_CHROMEOS_ASH) - #if !BUILDFLAG(IS_ANDROID) // App Service related flags. See components/services/app_service/README.md. const base::Feature kAppServiceLoadIconWithoutMojom{ @@ -136,6 +129,11 @@ "BackgroundModeAllowRestart", base::FEATURE_DISABLED_BY_DEFAULT}; #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +#if !BUILDFLAG(IS_ANDROID) +const base::Feature kBlockMigratedDefaultChromeAppSync{ + "BlockMigratedDefaultChromeAppSync", base::FEATURE_ENABLED_BY_DEFAULT}; +#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) // Enable Borealis on Chrome OS. const base::Feature kBorealis{"Borealis", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -261,14 +259,6 @@ "PreinstalledWebAppDuplicationFixer", base::FEATURE_ENABLED_BY_DEFAULT}; #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ - BUILDFLAG(IS_FUCHSIA) -// Enables Desktop PWAs shortcuts menu to be visible and executable in ChromeOS, -// MacOS and Linux. -const base::Feature kDesktopPWAsAppIconShortcutsMenuUI{ - "DesktopPWAsAppIconShortcutsMenuUI", base::FEATURE_ENABLED_BY_DEFAULT}; -#endif - // API that allows PWAs manually minimizing, maximizing and restoring windows. const base::Feature kDesktopPWAsAdditionalWindowingControls{ "DesktopPWAsAdditionalWindowingControls",
diff --git a/chrome/common/chrome_features.h b/chrome/common/chrome_features.h index 70c18b7..602427f 100644 --- a/chrome/common/chrome_features.h +++ b/chrome/common/chrome_features.h
@@ -68,11 +68,6 @@ extern const base::Feature kAppDiscoveryForOobe; #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) -COMPONENT_EXPORT(CHROME_FEATURES) -extern const base::Feature kAppManagementIntentSettings; -#endif - #if !BUILDFLAG(IS_ANDROID) COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kAppServiceLoadIconWithoutMojom; @@ -109,6 +104,11 @@ extern const base::Feature kBackgroundModeAllowRestart; #endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +#if !BUILDFLAG(IS_ANDROID) +COMPONENT_EXPORT(CHROME_FEATURES) +extern const base::Feature kBlockMigratedDefaultChromeAppSync; +#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kBorealis; #endif // BUILDFLAG(IS_CHROMEOS_ASH) @@ -188,12 +188,6 @@ extern const base::Feature kPreinstalledWebAppDuplicationFixer; #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \ - BUILDFLAG(IS_FUCHSIA) -COMPONENT_EXPORT(CHROME_FEATURES) -extern const base::Feature kDesktopPWAsAppIconShortcutsMenuUI; -#endif - COMPONENT_EXPORT(CHROME_FEATURES) extern const base::Feature kDesktopPWAsAdditionalWindowingControls;
diff --git a/chrome/common/extensions/api/common_extension_api_unittest.cc b/chrome/common/extensions/api/common_extension_api_unittest.cc index e55bda3..d90fa51b 100644 --- a/chrome/common/extensions/api/common_extension_api_unittest.cc +++ b/chrome/common/extensions/api/common_extension_api_unittest.cc
@@ -235,7 +235,7 @@ bool expected = test_data[i].expect_is_available; Feature::Availability availability = api.IsAvailable( test_data[i].api_full_name, nullptr, test_data[i].context, - test_data[i].url, CheckAliasStatus::NOT_ALLOWED); + test_data[i].url, CheckAliasStatus::NOT_ALLOWED, kUnspecifiedContextId); EXPECT_EQ(expected, availability.is_available()) << base::StringPrintf("Test %d: Feature '%s' was %s: %s", static_cast<int>(i), @@ -257,19 +257,20 @@ ASSERT_FALSE(api.IsAvailable("alias_api_source", nullptr, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); ASSERT_TRUE(api.IsAvailable("alias_api_source", nullptr, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::ALLOWED) + CheckAliasStatus::ALLOWED, kUnspecifiedContextId) .is_available()); ASSERT_TRUE(api.IsAvailable("alias_api_source.bar", nullptr, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::ALLOWED) + CheckAliasStatus::ALLOWED, kUnspecifiedContextId) .is_available()); ASSERT_FALSE(api.IsAvailable("alias_api_source.foo", nullptr, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::ALLOWED) + CheckAliasStatus::ALLOWED, kUnspecifiedContextId) .is_available()); scoped_refptr<const Extension> extension = @@ -285,10 +286,10 @@ ASSERT_TRUE(test_feature); ASSERT_FALSE(api.IsAnyFeatureAvailableToContext( *test_feature, extension.get(), Feature::UNBLESSED_EXTENSION_CONTEXT, - GURL(), CheckAliasStatus::NOT_ALLOWED)); + GURL(), CheckAliasStatus::NOT_ALLOWED, kUnspecifiedContextId)); EXPECT_TRUE(api.IsAnyFeatureAvailableToContext( *test_feature, extension.get(), Feature::UNBLESSED_EXTENSION_CONTEXT, - GURL(), CheckAliasStatus::ALLOWED)); + GURL(), CheckAliasStatus::ALLOWED, kUnspecifiedContextId)); } TEST(ExtensionAPITest, IsAnyFeatureAvailableToContext) { @@ -375,7 +376,8 @@ EXPECT_EQ(test_data[i].expect_is_available, api.IsAnyFeatureAvailableToContext( *test_feature, test_data[i].extension, test_data[i].context, - test_data[i].url, CheckAliasStatus::NOT_ALLOWED)) + test_data[i].url, CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId)) << i; } } @@ -433,11 +435,12 @@ std::unique_ptr<base::AutoReset<mojom::FeatureSessionType>> current_session( ScopedCurrentFeatureSessionType(test.current_session_type)); - EXPECT_EQ(test.expect_available, - api.IsAvailable(test.api_name, app.get(), - Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) - .is_available()) + EXPECT_EQ( + test.expect_available, + api.IsAvailable(test.api_name, app.get(), + Feature::BLESSED_EXTENSION_CONTEXT, GURL(), + CheckAliasStatus::NOT_ALLOWED, kUnspecifiedContextId) + .is_available()) << "Test case (" << test.api_name << ", " << static_cast<int>(test.current_session_type) << ")."; } @@ -512,44 +515,48 @@ // "storage" is completely unprivileged. EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext( *api_features.GetFeature("storage"), nullptr, - Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED)); + Feature::BLESSED_EXTENSION_CONTEXT, GURL(), CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId)); EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext( *api_features.GetFeature("storage"), nullptr, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED)); + CheckAliasStatus::NOT_ALLOWED, kUnspecifiedContextId)); EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext( *api_features.GetFeature("storage"), nullptr, - Feature::CONTENT_SCRIPT_CONTEXT, GURL(), CheckAliasStatus::NOT_ALLOWED)); + Feature::CONTENT_SCRIPT_CONTEXT, GURL(), CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId)); // "extension" is partially unprivileged. EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext( *api_features.GetFeature("extension"), nullptr, - Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED)); + Feature::BLESSED_EXTENSION_CONTEXT, GURL(), CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId)); EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext( *api_features.GetFeature("extension"), nullptr, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED)); + CheckAliasStatus::NOT_ALLOWED, kUnspecifiedContextId)); EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext( *api_features.GetFeature("extension"), nullptr, - Feature::CONTENT_SCRIPT_CONTEXT, GURL(), CheckAliasStatus::NOT_ALLOWED)); + Feature::CONTENT_SCRIPT_CONTEXT, GURL(), CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId)); EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext( *api_features.GetFeature("extension.getURL"), nullptr, - Feature::CONTENT_SCRIPT_CONTEXT, GURL(), CheckAliasStatus::NOT_ALLOWED)); + Feature::CONTENT_SCRIPT_CONTEXT, GURL(), CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId)); // "history" is entirely privileged. EXPECT_TRUE(extension_api->IsAnyFeatureAvailableToContext( *api_features.GetFeature("history"), nullptr, - Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED)); + Feature::BLESSED_EXTENSION_CONTEXT, GURL(), CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId)); EXPECT_FALSE(extension_api->IsAnyFeatureAvailableToContext( *api_features.GetFeature("history"), nullptr, Feature::UNBLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED)); + CheckAliasStatus::NOT_ALLOWED, kUnspecifiedContextId)); EXPECT_FALSE(extension_api->IsAnyFeatureAvailableToContext( *api_features.GetFeature("history"), nullptr, - Feature::CONTENT_SCRIPT_CONTEXT, GURL(), CheckAliasStatus::NOT_ALLOWED)); + Feature::CONTENT_SCRIPT_CONTEXT, GURL(), CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId)); } scoped_refptr<Extension> CreateHostedApp() { @@ -608,27 +615,32 @@ EXPECT_FALSE(extension_api ->IsAvailable("runtime", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); EXPECT_FALSE(extension_api ->IsAvailable("runtime.id", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); EXPECT_FALSE(extension_api ->IsAvailable("runtime.sendMessage", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); EXPECT_FALSE(extension_api ->IsAvailable("runtime.sendNativeMessage", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); EXPECT_FALSE(extension_api ->IsAvailable("tabs.create", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); } @@ -648,19 +660,22 @@ ->IsAvailable("app", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL("http://foo.com"), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); EXPECT_TRUE(extension_api ->IsAvailable("app.runtime", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL("http://foo.com"), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); EXPECT_TRUE(extension_api ->IsAvailable("app.window", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL("http://foo.com"), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); } // Make sure chrome.app.runtime and chrome.app.window are not available to @@ -673,19 +688,22 @@ ->IsAvailable("app", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL("http://foo.com"), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); EXPECT_FALSE(extension_api ->IsAvailable("app.runtime", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL("http://foo.com"), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); EXPECT_FALSE(extension_api ->IsAvailable("app.window", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL("http://foo.com"), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); } } @@ -700,11 +718,13 @@ ExtensionAPI::CreateWithDefaultConfiguration()); EXPECT_TRUE(api->IsAvailable("ttsEngine", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); EXPECT_FALSE(api->IsAvailable("tts", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); } @@ -717,11 +737,13 @@ ExtensionAPI::CreateWithDefaultConfiguration()); EXPECT_FALSE(api->IsAvailable("ttsEngine", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); EXPECT_TRUE(api->IsAvailable("tts", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); } } @@ -730,7 +752,7 @@ ExtensionAPI* api, const std::string& api_name, const std::string& url) { return api ->IsAvailable(api_name, nullptr, Feature::WEB_PAGE_CONTEXT, GURL(url), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, kUnspecifiedContextId) .is_available(); } @@ -960,12 +982,13 @@ scoped_refptr<const Extension> extension = ExtensionBuilder("Test").Build(); for (size_t i = 0; i < base::size(kTests); ++i) { - EXPECT_EQ(kTests[i].expect_success, - extension_api - ->IsAvailable(kTests[i].permission_name, extension.get(), - Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) - .is_available()) + EXPECT_EQ( + kTests[i].expect_success, + extension_api + ->IsAvailable(kTests[i].permission_name, extension.get(), + Feature::BLESSED_EXTENSION_CONTEXT, GURL(), + CheckAliasStatus::NOT_ALLOWED, kUnspecifiedContextId) + .is_available()) << "Permission being tested: " << kTests[i].permission_name; } } @@ -982,12 +1005,14 @@ EXPECT_TRUE(extension_api ->IsAvailable("browserAction", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); EXPECT_FALSE(extension_api ->IsAvailable("pageAction", extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, GURL(), - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, + kUnspecifiedContextId) .is_available()); }
diff --git a/chrome/common/extensions/api/omnibox.json b/chrome/common/extensions/api/omnibox.json index 22a4168..a7280ed 100644 --- a/chrome/common/extensions/api/omnibox.json +++ b/chrome/common/extensions/api/omnibox.json
@@ -31,16 +31,6 @@ } }, { - "id": "MatchClassificationRaw", - "nodoc": true, - "type": "object", - "description": "The style ranges for the description, as provided by ToValue().", - "properties": { - "offset": { "type": "integer" }, - "type": { "type": "integer" } - } - }, - { "id": "SuggestResult", "type": "object", "description": "A suggest result.", @@ -69,16 +59,6 @@ "name": "matchClassification", "$ref": "MatchClassification" } - }, - "descriptionStylesRaw": { - "nodoc": true, - "optional": true, - "type": "array", - "description": "An array of style ranges for the description, as provided by ToValue().", - "items": { - "name": "matchClassificationRaw", - "$ref": "MatchClassificationRaw" - } } } }, @@ -102,16 +82,6 @@ "name": "matchClassification", "$ref": "MatchClassification" } - }, - "descriptionStylesRaw": { - "nodoc": true, - "optional": true, - "type": "array", - "description": "An array of style ranges for the description, as provided by ToValue().", - "items": { - "name": "matchClassificationRaw", - "$ref": "MatchClassificationRaw" - } } } }
diff --git a/chrome/renderer/chrome_content_renderer_client.cc b/chrome/renderer/chrome_content_renderer_client.cc index fe54d804..a14bff6 100644 --- a/chrome/renderer/chrome_content_renderer_client.cc +++ b/chrome/renderer/chrome_content_renderer_client.cc
@@ -1477,9 +1477,9 @@ browser_interface_broker_.get()); } -void ChromeContentRendererClient::AddSupportedKeySystems( - std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) { - key_systems_provider_.AddSupportedKeySystems(key_systems); +void ChromeContentRendererClient::GetSupportedKeySystems( + media::GetSupportedKeySystemsCB cb) { + key_systems_provider_.GetSupportedKeySystems(std::move(cb)); } bool ChromeContentRendererClient::IsKeySystemsUpdateNeeded() {
diff --git a/chrome/renderer/chrome_content_renderer_client.h b/chrome/renderer/chrome_content_renderer_client.h index 460fd956..2c37b6c 100644 --- a/chrome/renderer/chrome_content_renderer_client.h +++ b/chrome/renderer/chrome_content_renderer_client.h
@@ -160,9 +160,7 @@ content::RenderFrame* render_frame, media::SpeechRecognitionClient::OnReadyCallback callback) override; #endif - void AddSupportedKeySystems( - std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) - override; + void GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb) override; bool IsKeySystemsUpdateNeeded() override; bool IsPluginAllowedToUseCameraDeviceAPI(const GURL& url) override; void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override;
diff --git a/chrome/renderer/media/chrome_key_systems.cc b/chrome/renderer/media/chrome_key_systems.cc index 2747416..0cdaa37d 100644 --- a/chrome/renderer/media/chrome_key_systems.cc +++ b/chrome/renderer/media/chrome_key_systems.cc
@@ -56,26 +56,50 @@ using media::EmeFeatureSupport; using media::EmeSessionTypeSupport; using media::KeySystemProperties; +using media::KeySystemPropertiesVector; using media::SupportedCodecs; namespace { #if BUILDFLAG(ENABLE_LIBRARY_CDMS) -// External Clear Key (used for testing). -void AddExternalClearKey( - std::vector<std::unique_ptr<KeySystemProperties>>* key_systems) { - static const char kExternalClearKeyKeySystem[] = - "org.chromium.externalclearkey"; +// Helper callback for chained key system query operations. +using TrampolineCB = media::GetSupportedKeySystemsCB; + +void OnExternalClearKeyQueried( + TrampolineCB cb, + KeySystemPropertiesVector key_systems, + bool is_supported, + media::mojom::KeySystemCapabilityPtr capability) { + DVLOG(1) << __func__; // TODO(xhwang): Actually use `capability` to determine capabilities. - media::mojom::KeySystemCapabilityPtr capability; - if (!content::IsKeySystemSupported(kExternalClearKeyKeySystem, &capability)) { + if (is_supported) { + key_systems.push_back(std::make_unique<cdm::ExternalClearKeyProperties>()); + } else { DVLOG(1) << "External Clear Key not supported"; + } + + std::move(cb).Run(std::move(key_systems)); +} + +// External Clear Key (used for testing). +void QueryExternalClearKey(TrampolineCB cb, + KeySystemPropertiesVector key_systems) { + DVLOG(1) << __func__; + + if (!base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting)) { + std::move(cb).Run(std::move(key_systems)); return; } - key_systems->push_back(std::make_unique<cdm::ExternalClearKeyProperties>()); + static const char kExternalClearKeyKeySystem[] = + "org.chromium.externalclearkey"; + + content::IsKeySystemSupported( + kExternalClearKeyKeySystem, + base::BindOnce(&OnExternalClearKeyQueried, std::move(cb), + std::move(key_systems))); } #if BUILDFLAG(ENABLE_WIDEVINE) @@ -249,21 +273,8 @@ #endif // BUILDFLAG(IS_CHROMEOS) } -void AddWidevine( - std::vector<std::unique_ptr<KeySystemProperties>>* key_systems) { -#if defined(WIDEVINE_CDM_MIN_GLIBC_VERSION) - base::Version glibc_version(gnu_get_libc_version()); - DCHECK(glibc_version.IsValid()); - if (glibc_version < base::Version(WIDEVINE_CDM_MIN_GLIBC_VERSION)) - return; -#endif // defined(WIDEVINE_CDM_MIN_GLIBC_VERSION) - - media::mojom::KeySystemCapabilityPtr capability; - if (!content::IsKeySystemSupported(kWidevineKeySystem, &capability)) { - DVLOG(1) << "Widevine CDM is not currently available."; - return; - } - +bool AddWidevine(media::mojom::KeySystemCapabilityPtr capability, + KeySystemPropertiesVector* key_systems) { // Codecs and encryption schemes. SupportedCodecs codecs = media::EME_CODEC_NONE; SupportedCodecs hw_secure_codecs = media::EME_CODEC_NONE; @@ -277,7 +288,7 @@ if (!base::Contains(capability->sw_secure_capability->session_types, media::CdmSessionType::kTemporary)) { DVLOG(1) << "Temporary sessions must be supported."; - return; + return false; } cdm_supports_persistent_license = @@ -293,7 +304,7 @@ if (!base::Contains(capability->hw_secure_capability->session_types, media::CdmSessionType::kTemporary)) { DVLOG(1) << "Temporary sessions must be supported."; - return; + return false; } // TODO(b/186035558): With a single flag we can't distinguish persistent @@ -334,25 +345,62 @@ hw_secure_encryption_schemes, max_audio_robustness, max_video_robustness, persistent_license_support, persistent_state_support, distinctive_identifier_support)); + return true; +} + +void OnWidevineQueried(TrampolineCB cb, + KeySystemPropertiesVector key_systems, + bool is_supported, + media::mojom::KeySystemCapabilityPtr capability) { + DVLOG(1) << __func__; + + if (is_supported) { + if (!AddWidevine(std::move(capability), &key_systems)) + DVLOG(1) << "Invalid Widevine CDM capability."; + } else { + DVLOG(1) << "Widevine CDM is not currently available."; + } + + std::move(cb).Run(std::move(key_systems)); +} + +void QueryWidevine(TrampolineCB cb, KeySystemPropertiesVector key_systems) { + DVLOG(1) << __func__; + +#if defined(WIDEVINE_CDM_MIN_GLIBC_VERSION) + base::Version glibc_version(gnu_get_libc_version()); + DCHECK(glibc_version.IsValid()); + if (glibc_version < base::Version(WIDEVINE_CDM_MIN_GLIBC_VERSION)) { + std::move(cb).Run(std::move(key_systems)); + return; + } +#endif // defined(WIDEVINE_CDM_MIN_GLIBC_VERSION) + + content::IsKeySystemSupported( + kWidevineKeySystem, base::BindOnce(&OnWidevineQueried, std::move(cb), + std::move(key_systems))); } #endif // BUILDFLAG(ENABLE_WIDEVINE) #endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) } // namespace -void AddChromeKeySystems( - std::vector<std::unique_ptr<KeySystemProperties>>* key_systems) { -#if BUILDFLAG(ENABLE_LIBRARY_CDMS) - if (base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting)) - AddExternalClearKey(key_systems); - -#if BUILDFLAG(ENABLE_WIDEVINE) - AddWidevine(key_systems); -#endif // BUILDFLAG(ENABLE_WIDEVINE) - -#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) +void GetChromeKeySystems(media::GetSupportedKeySystemsCB cb) { + KeySystemPropertiesVector key_systems; #if BUILDFLAG(IS_ANDROID) - cdm::AddAndroidWidevine(key_systems); + cdm::AddAndroidWidevine(&key_systems); #endif // BUILDFLAG(IS_ANDROID) + +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) +#if BUILDFLAG(ENABLE_WIDEVINE) + auto trampoline_cb = base::BindOnce(&QueryWidevine, std::move(cb)); +#else + auto trampoline_cb = std::move(cb); +#endif // BUILDFLAG(ENABLE_WIDEVINE) + + QueryExternalClearKey(std::move(trampoline_cb), std::move(key_systems)); +#else + std::move(cb).Run(std::move(key_systems)); +#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS) }
diff --git a/chrome/renderer/media/chrome_key_systems.h b/chrome/renderer/media/chrome_key_systems.h index c589b250..2f7b513 100644 --- a/chrome/renderer/media/chrome_key_systems.h +++ b/chrome/renderer/media/chrome_key_systems.h
@@ -8,12 +8,9 @@ #include <memory> #include <vector> -namespace media { -class KeySystemProperties; -} +#include "media/base/key_system_properties.h" -// Register the key systems supported by populating `key_systems`. -void AddChromeKeySystems( - std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems); +// Register the key systems supported by the chrome/ layer. +void GetChromeKeySystems(media::GetSupportedKeySystemsCB cb); #endif // CHROME_RENDERER_MEDIA_CHROME_KEY_SYSTEMS_H_
diff --git a/chrome/renderer/media/chrome_key_systems_provider.cc b/chrome/renderer/media/chrome_key_systems_provider.cc index 5b0e3bd..e359643 100644 --- a/chrome/renderer/media/chrome_key_systems_provider.cc +++ b/chrome/renderer/media/chrome_key_systems_provider.cc
@@ -4,7 +4,6 @@ #include "chrome/renderer/media/chrome_key_systems_provider.h" -#include "base/time/default_tick_clock.h" #include "chrome/renderer/media/chrome_key_systems.h" #include "third_party/widevine/cdm/buildflags.h" @@ -12,38 +11,23 @@ #include "third_party/widevine/cdm/widevine_cdm_common.h" // nogncheck #endif -ChromeKeySystemsProvider::ChromeKeySystemsProvider() - : has_updated_(false), - is_update_needed_(true), - tick_clock_(base::DefaultTickClock::GetInstance()) {} +ChromeKeySystemsProvider::ChromeKeySystemsProvider() = default; +ChromeKeySystemsProvider::~ChromeKeySystemsProvider() = default; -ChromeKeySystemsProvider::~ChromeKeySystemsProvider() {} - -void ChromeKeySystemsProvider::AddSupportedKeySystems( - std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) { - DCHECK(key_systems); +void ChromeKeySystemsProvider::GetSupportedKeySystems( + media::GetSupportedKeySystemsCB cb) { DCHECK(thread_checker_.CalledOnValidThread()); if (!test_provider_.is_null()) { - test_provider_.Run(key_systems); - } else { - AddChromeKeySystems(key_systems); + media::KeySystemPropertiesVector key_systems; + test_provider_.Run(&key_systems); + OnSupportedKeySystemsReady(std::move(cb), std::move(key_systems)); + return; } - has_updated_ = true; - last_update_time_ticks_ = tick_clock_->NowTicks(); - -// Check whether all potentially supported key systems are supported. If so, -// no need to update again. -#if BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT) - for (const auto& properties : *key_systems) { - if (properties->GetBaseKeySystemName() == kWidevineKeySystem) { - is_update_needed_ = false; - } - } -#else - is_update_needed_ = false; -#endif + GetChromeKeySystems( + base::BindOnce(&ChromeKeySystemsProvider::OnSupportedKeySystemsReady, + weak_factory_.GetWeakPtr(), std::move(cb))); } bool ChromeKeySystemsProvider::IsKeySystemsUpdateNeeded() { @@ -59,8 +43,8 @@ if (!is_update_needed_) return false; - // The update could be expensive. For example, it could involve a sync IPC to - // the browser process. Use a minimum update interval to avoid unnecessarily + // The update could be expensive. For example, it could involve an IPC to the + // browser process. Use a minimum update interval to avoid unnecessarily // frequent update. static const int kMinUpdateIntervalInMilliseconds = 1000; if ((tick_clock_->NowTicks() - last_update_time_ticks_).InMilliseconds() < @@ -80,3 +64,24 @@ KeySystemsProviderDelegate test_provider) { test_provider_ = std::move(test_provider); } + +void ChromeKeySystemsProvider::OnSupportedKeySystemsReady( + media::GetSupportedKeySystemsCB cb, + media::KeySystemPropertiesVector key_systems) { + has_updated_ = true; + last_update_time_ticks_ = tick_clock_->NowTicks(); + +// Check whether all potentially supported key systems are supported. If so, +// no need to update again. +#if BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT) + for (const auto& properties : key_systems) { + if (properties->GetBaseKeySystemName() == kWidevineKeySystem) { + is_update_needed_ = false; + } + } +#else + is_update_needed_ = false; +#endif + + std::move(cb).Run(std::move(key_systems)); +}
diff --git a/chrome/renderer/media/chrome_key_systems_provider.h b/chrome/renderer/media/chrome_key_systems_provider.h index 4de35d74..5753760 100644 --- a/chrome/renderer/media/chrome_key_systems_provider.h +++ b/chrome/renderer/media/chrome_key_systems_provider.h
@@ -9,31 +9,29 @@ #include <vector> #include "base/callback.h" +#include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" +#include "base/time/default_tick_clock.h" #include "base/time/tick_clock.h" #include "base/time/time.h" #include "media/base/key_system_properties.h" -typedef std::vector<std::unique_ptr<media::KeySystemProperties>> - KeySystemPropertiesVector; -typedef base::RepeatingCallback<void(KeySystemPropertiesVector*)> - KeySystemsProviderDelegate; +using KeySystemsProviderDelegate = + base::RepeatingCallback<void(media::KeySystemPropertiesVector*)>; class ChromeKeySystemsProvider { public: ChromeKeySystemsProvider(); - ChromeKeySystemsProvider(const ChromeKeySystemsProvider&) = delete; ChromeKeySystemsProvider& operator=(const ChromeKeySystemsProvider&) = delete; - ~ChromeKeySystemsProvider(); - // Adds properties for supported key systems. - void AddSupportedKeySystems(KeySystemPropertiesVector* key_systems); + // Gets supported key system properties. + void GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb); // Returns whether client key systems properties should be updated. // TODO(chcunningham): Refactor this to a proper change "observer" API that is - // less fragile (don't assume AddSupportedKeySystems has just one caller). + // less fragile (don't assume GetSupportedKeySystems has just one caller). bool IsKeySystemsUpdateNeeded(); void SetTickClockForTesting(const base::TickClock* tick_clock); @@ -41,18 +39,21 @@ void SetProviderDelegateForTesting(KeySystemsProviderDelegate test_provider); private: - // Whether AddSupportedKeySystems() has ever been called. - bool has_updated_; + void OnSupportedKeySystemsReady(media::GetSupportedKeySystemsCB cb, + media::KeySystemPropertiesVector key_systems); + + // Whether GetSupportedKeySystems() has ever been called. + bool has_updated_ = false; // Whether a future update is needed. For example, when some potentially // supported key systems are NOT supported yet. This could happen when the // required component for a key system is not yet available. - bool is_update_needed_; + bool is_update_needed_ = true; // Throttle how often we signal an update is needed to avoid unnecessary high // frequency of expensive IPC calls. base::TimeTicks last_update_time_ticks_; - const base::TickClock* tick_clock_; + const base::TickClock* tick_clock_ = base::DefaultTickClock::GetInstance(); // Ensure all methods are called from the same (Main) thread. base::ThreadChecker thread_checker_; @@ -60,6 +61,8 @@ // For unit tests to inject their own key systems. Will bypass adding default // Chrome key systems when set. KeySystemsProviderDelegate test_provider_; + + base::WeakPtrFactory<ChromeKeySystemsProvider> weak_factory_{this}; }; #endif // CHROME_RENDERER_MEDIA_CHROME_KEY_SYSTEMS_PROVIDER_H_
diff --git a/chrome/renderer/media/chrome_key_systems_provider_unittest.cc b/chrome/renderer/media/chrome_key_systems_provider_unittest.cc index e09b043..605c1cb 100644 --- a/chrome/renderer/media/chrome_key_systems_provider_unittest.cc +++ b/chrome/renderer/media/chrome_key_systems_provider_unittest.cc
@@ -10,7 +10,9 @@ #include "base/bind.h" #include "base/callback_helpers.h" +#include "base/test/bind.h" #include "base/test/simple_test_tick_clock.h" +#include "base/test/task_environment.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/widevine/cdm/buildflags.h" #include "third_party/widevine/cdm/widevine_cdm_common.h" @@ -92,10 +94,17 @@ bool include_widevine_; }; +void CopyKeySystems(media::KeySystemPropertiesVector* output, + media::KeySystemPropertiesVector input) { + *output = std::move(input); +} + } // namespace TEST(ChromeKeySystemsProviderTest, IsKeySystemsUpdateNeeded) { + base::test::TaskEnvironment task_environment_; ChromeKeySystemsProvider key_systems_provider; + media::KeySystemPropertiesVector key_systems; base::SimpleTestTickClock tick_clock; key_systems_provider.SetTickClockForTesting(&tick_clock); @@ -109,10 +118,10 @@ // IsKeySystemsUpdateNeeded() always returns true after construction. EXPECT_TRUE(key_systems_provider.IsKeySystemsUpdateNeeded()); - std::vector<std::unique_ptr<media::KeySystemProperties>> key_systems; - key_systems_provider.AddSupportedKeySystems(&key_systems); + key_systems_provider.GetSupportedKeySystems( + base::BindOnce(&CopyKeySystems, &key_systems)); - // No update needed immediately after AddSupportedKeySystems() call. + // No update needed immediately after GetSupportedKeySystems() call. EXPECT_FALSE(key_systems_provider.IsKeySystemsUpdateNeeded()); // Widevine not initially provided. @@ -133,7 +142,9 @@ // Now add Widevine. provider_delegate->set_include_widevine(true); key_systems.clear(); - key_systems_provider.AddSupportedKeySystems(&key_systems); + + key_systems_provider.GetSupportedKeySystems( + base::BindOnce(&CopyKeySystems, &key_systems)); // Widevine should now be among the list. bool found_widevine = false;
diff --git a/chrome/services/sharing/nearby/BUILD.gn b/chrome/services/sharing/nearby/BUILD.gn index 41f557c..409bd678 100644 --- a/chrome/services/sharing/nearby/BUILD.gn +++ b/chrome/services/sharing/nearby/BUILD.gn
@@ -22,7 +22,7 @@ "//base", "//chrome/services/sharing/public/cpp", "//mojo/public/cpp/bindings", - "//third_party/nearby:core", + "//third_party/nearby:connections", ] deps = [ @@ -48,6 +48,6 @@ "//chromeos/services/network_config/public/cpp:test_support", "//testing/gmock", "//testing/gtest", - "//third_party/nearby:core_internal_test", + "//third_party/nearby:connections_test_util", ] }
diff --git a/chrome/services/sharing/nearby/nearby_connections.cc b/chrome/services/sharing/nearby/nearby_connections.cc index f7615ac..943c843 100644 --- a/chrome/services/sharing/nearby/nearby_connections.cc +++ b/chrome/services/sharing/nearby/nearby_connections.cc
@@ -19,7 +19,7 @@ #include "chrome/services/sharing/nearby/nearby_connections_conversions.h" #include "chrome/services/sharing/nearby/platform/input_file.h" #include "services/network/public/mojom/p2p.mojom.h" -#include "third_party/nearby/src/cpp/core/core.h" +#include "third_party/nearby/src/connections/core.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/nearby_connections.h b/chrome/services/sharing/nearby/nearby_connections.h index 919d5c5..3d4b602 100644 --- a/chrome/services/sharing/nearby/nearby_connections.h +++ b/chrome/services/sharing/nearby/nearby_connections.h
@@ -30,7 +30,7 @@ #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/shared_remote.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/nearby/src/cpp/core/internal/service_controller_router.h" +#include "third_party/nearby/src/connections/implementation/service_controller_router.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/nearby_connections_conversions.h b/chrome/services/sharing/nearby/nearby_connections_conversions.h index 330658e..7ad7973 100644 --- a/chrome/services/sharing/nearby/nearby_connections_conversions.h +++ b/chrome/services/sharing/nearby/nearby_connections_conversions.h
@@ -11,7 +11,7 @@ #include "ash/services/nearby/public/mojom/nearby_connections.mojom-forward.h" #include "ash/services/nearby/public/mojom/nearby_connections_types.mojom-forward.h" #include "base/callback_forward.h" -#include "third_party/nearby/src/cpp/core/params.h" +#include "third_party/nearby/src/connections/params.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.cc b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.cc index 24983d3..d5a8b01 100644 --- a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.cc +++ b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.cc
@@ -8,8 +8,8 @@ #include "base/containers/contains.h" #include "chrome/browser/nearby_sharing/logging/logging.h" -#include "third_party/nearby/src/cpp/platform/base/exception.h" -#include "third_party/nearby/src/cpp/platform/base/input_stream.h" +#include "third_party/nearby/src/internal/platform/exception.h" +#include "third_party/nearby/src/internal/platform/input_stream.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.h b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.h index 28bc273f..c6a9c94 100644 --- a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.h +++ b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.h
@@ -8,8 +8,8 @@ #include <memory> #include <unordered_map> -#include "third_party/nearby/src/cpp/core/payload.h" -#include "third_party/nearby/src/cpp/platform/base/byte_array.h" +#include "third_party/nearby/src/connections/payload.h" +#include "third_party/nearby/src/internal/platform/byte_array.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager_unittest.cc b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager_unittest.cc index b9bcac75..bb9e241 100644 --- a/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager_unittest.cc +++ b/chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager_unittest.cc
@@ -5,10 +5,10 @@ #include "chrome/services/sharing/nearby/nearby_connections_stream_buffer_manager.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/nearby/src/cpp/core/payload.h" -#include "third_party/nearby/src/cpp/platform/base/byte_array.h" -#include "third_party/nearby/src/cpp/platform/base/exception.h" -#include "third_party/nearby/src/cpp/platform/base/input_stream.h" +#include "third_party/nearby/src/connections/payload.h" +#include "third_party/nearby/src/internal/platform/byte_array.h" +#include "third_party/nearby/src/internal/platform/exception.h" +#include "third_party/nearby/src/internal/platform/input_stream.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/nearby_connections_unittest.cc b/chrome/services/sharing/nearby/nearby_connections_unittest.cc index bdd9db8..9a26bfe 100644 --- a/chrome/services/sharing/nearby/nearby_connections_unittest.cc +++ b/chrome/services/sharing/nearby/nearby_connections_unittest.cc
@@ -35,7 +35,7 @@ #include "mojo/public/cpp/bindings/self_owned_receiver.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -#include "third_party/nearby/src/cpp/core/internal/mock_service_controller_router.h" +#include "third_party/nearby/src/connections/implementation/mock_service_controller_router.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform.cc b/chrome/services/sharing/nearby/platform.cc index bd367ad..694666e 100644 --- a/chrome/services/sharing/nearby/platform.cc +++ b/chrome/services/sharing/nearby/platform.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/nearby/src/cpp/platform/api/platform.h" +#include "third_party/nearby/src/internal/platform/implementation/platform.h" #include "ash/services/nearby/public/mojom/firewall_hole.mojom.h" #include "ash/services/nearby/public/mojom/tcp_socket_factory.mojom.h" @@ -29,22 +29,22 @@ #include "chromeos/services/network_config/public/mojom/cros_network_config.mojom.h" #include "device/bluetooth/public/mojom/adapter.mojom.h" #include "mojo/public/cpp/bindings/shared_remote.h" -#include "third_party/nearby/src/cpp/platform/api/atomic_boolean.h" -#include "third_party/nearby/src/cpp/platform/api/atomic_reference.h" -#include "third_party/nearby/src/cpp/platform/api/ble.h" -#include "third_party/nearby/src/cpp/platform/api/ble_v2.h" -#include "third_party/nearby/src/cpp/platform/api/bluetooth_adapter.h" -#include "third_party/nearby/src/cpp/platform/api/bluetooth_classic.h" -#include "third_party/nearby/src/cpp/platform/api/condition_variable.h" -#include "third_party/nearby/src/cpp/platform/api/count_down_latch.h" -#include "third_party/nearby/src/cpp/platform/api/log_message.h" -#include "third_party/nearby/src/cpp/platform/api/mutex.h" -#include "third_party/nearby/src/cpp/platform/api/scheduled_executor.h" -#include "third_party/nearby/src/cpp/platform/api/server_sync.h" -#include "third_party/nearby/src/cpp/platform/api/submittable_executor.h" -#include "third_party/nearby/src/cpp/platform/api/webrtc.h" -#include "third_party/nearby/src/cpp/platform/api/wifi.h" -#include "third_party/nearby/src/cpp/platform/impl/shared/file.h" +#include "third_party/nearby/src/internal/platform/implementation/atomic_boolean.h" +#include "third_party/nearby/src/internal/platform/implementation/atomic_reference.h" +#include "third_party/nearby/src/internal/platform/implementation/ble.h" +#include "third_party/nearby/src/internal/platform/implementation/ble_v2.h" +#include "third_party/nearby/src/internal/platform/implementation/bluetooth_adapter.h" +#include "third_party/nearby/src/internal/platform/implementation/bluetooth_classic.h" +#include "third_party/nearby/src/internal/platform/implementation/condition_variable.h" +#include "third_party/nearby/src/internal/platform/implementation/count_down_latch.h" +#include "third_party/nearby/src/internal/platform/implementation/log_message.h" +#include "third_party/nearby/src/internal/platform/implementation/mutex.h" +#include "third_party/nearby/src/internal/platform/implementation/scheduled_executor.h" +#include "third_party/nearby/src/internal/platform/implementation/server_sync.h" +#include "third_party/nearby/src/internal/platform/implementation/shared/file.h" +#include "third_party/nearby/src/internal/platform/implementation/submittable_executor.h" +#include "third_party/nearby/src/internal/platform/implementation/webrtc.h" +#include "third_party/nearby/src/internal/platform/implementation/wifi.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/atomic_boolean.h b/chrome/services/sharing/nearby/platform/atomic_boolean.h index 632c2d4..e7443b1a 100644 --- a/chrome/services/sharing/nearby/platform/atomic_boolean.h +++ b/chrome/services/sharing/nearby/platform/atomic_boolean.h
@@ -7,7 +7,7 @@ #include <atomic> -#include "third_party/nearby/src/cpp/platform/api/atomic_boolean.h" +#include "third_party/nearby/src/internal/platform/implementation/atomic_boolean.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/atomic_uint32.h b/chrome/services/sharing/nearby/platform/atomic_uint32.h index ae147f1..8d7614c7 100644 --- a/chrome/services/sharing/nearby/platform/atomic_uint32.h +++ b/chrome/services/sharing/nearby/platform/atomic_uint32.h
@@ -7,7 +7,7 @@ #include <atomic> -#include "third_party/nearby/src/cpp/platform/api/atomic_reference.h" +#include "third_party/nearby/src/internal/platform/implementation/atomic_reference.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/bidirectional_stream.h b/chrome/services/sharing/nearby/platform/bidirectional_stream.h index 78f2c2a..e5d9b61 100644 --- a/chrome/services/sharing/nearby/platform/bidirectional_stream.h +++ b/chrome/services/sharing/nearby/platform/bidirectional_stream.h
@@ -10,7 +10,7 @@ #include "ash/services/nearby/public/mojom/nearby_connections_types.mojom.h" #include "base/memory/scoped_refptr.h" #include "mojo/public/cpp/system/data_pipe.h" -#include "third_party/nearby/src/cpp/platform/base/exception.h" +#include "third_party/nearby/src/internal/platform/exception.h" namespace base { class SequencedTaskRunner;
diff --git a/chrome/services/sharing/nearby/platform/ble_medium.h b/chrome/services/sharing/nearby/platform/ble_medium.h index e4bc113..5307fdc 100644 --- a/chrome/services/sharing/nearby/platform/ble_medium.h +++ b/chrome/services/sharing/nearby/platform/ble_medium.h
@@ -12,7 +12,7 @@ #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/shared_remote.h" -#include "third_party/nearby/src/cpp/platform/api/ble.h" +#include "third_party/nearby/src/internal/platform/implementation/ble.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/ble_peripheral.h b/chrome/services/sharing/nearby/platform/ble_peripheral.h index 7c6ab2b..308ff20 100644 --- a/chrome/services/sharing/nearby/platform/ble_peripheral.h +++ b/chrome/services/sharing/nearby/platform/ble_peripheral.h
@@ -10,7 +10,7 @@ #include "device/bluetooth/public/cpp/bluetooth_uuid.h" #include "device/bluetooth/public/mojom/adapter.mojom.h" -#include "third_party/nearby/src/cpp/platform/api/ble.h" +#include "third_party/nearby/src/internal/platform/implementation/ble.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_adapter.h b/chrome/services/sharing/nearby/platform/bluetooth_adapter.h index 7072283c..9326953 100644 --- a/chrome/services/sharing/nearby/platform/bluetooth_adapter.h +++ b/chrome/services/sharing/nearby/platform/bluetooth_adapter.h
@@ -9,7 +9,7 @@ #include "device/bluetooth/public/mojom/adapter.mojom.h" #include "mojo/public/cpp/bindings/shared_remote.h" -#include "third_party/nearby/src/cpp/platform/api/bluetooth_adapter.h" +#include "third_party/nearby/src/internal/platform/implementation/bluetooth_adapter.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.h b/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.h index 808baa2..5dd4c08 100644 --- a/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.h +++ b/chrome/services/sharing/nearby/platform/bluetooth_classic_medium.h
@@ -15,7 +15,7 @@ #include "mojo/public/cpp/bindings/remote.h" #include "mojo/public/cpp/bindings/shared_remote.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/nearby/src/cpp/platform/api/bluetooth_classic.h" +#include "third_party/nearby/src/internal/platform/implementation/bluetooth_classic.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_device.h b/chrome/services/sharing/nearby/platform/bluetooth_device.h index 73d641a..7cf773a 100644 --- a/chrome/services/sharing/nearby/platform/bluetooth_device.h +++ b/chrome/services/sharing/nearby/platform/bluetooth_device.h
@@ -10,7 +10,7 @@ #include "base/time/time.h" #include "device/bluetooth/public/mojom/adapter.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/nearby/src/cpp/platform/api/bluetooth_classic.h" +#include "third_party/nearby/src/internal/platform/implementation/bluetooth_classic.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_server_socket.cc b/chrome/services/sharing/nearby/platform/bluetooth_server_socket.cc index 336290a..cbeaf81 100644 --- a/chrome/services/sharing/nearby/platform/bluetooth_server_socket.cc +++ b/chrome/services/sharing/nearby/platform/bluetooth_server_socket.cc
@@ -8,7 +8,7 @@ #include "base/task/task_traits.h" #include "base/task/thread_pool.h" #include "chrome/services/sharing/nearby/platform/bluetooth_socket.h" -#include "third_party/nearby/src/cpp/platform/base/exception.h" +#include "third_party/nearby/src/internal/platform/exception.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_server_socket.h b/chrome/services/sharing/nearby/platform/bluetooth_server_socket.h index 14db462..7adf5af3 100644 --- a/chrome/services/sharing/nearby/platform/bluetooth_server_socket.h +++ b/chrome/services/sharing/nearby/platform/bluetooth_server_socket.h
@@ -10,7 +10,7 @@ #include "device/bluetooth/public/mojom/adapter.mojom.h" #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/shared_remote.h" -#include "third_party/nearby/src/cpp/platform/api/bluetooth_classic.h" +#include "third_party/nearby/src/internal/platform/implementation/bluetooth_classic.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/bluetooth_socket.h b/chrome/services/sharing/nearby/platform/bluetooth_socket.h index 6f2741e..d79e928 100644 --- a/chrome/services/sharing/nearby/platform/bluetooth_socket.h +++ b/chrome/services/sharing/nearby/platform/bluetooth_socket.h
@@ -12,7 +12,7 @@ #include "device/bluetooth/public/mojom/adapter.mojom.h" #include "mojo/public/cpp/bindings/shared_remote.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/nearby/src/cpp/platform/api/bluetooth_classic.h" +#include "third_party/nearby/src/internal/platform/implementation/bluetooth_classic.h" namespace base { class SequencedTaskRunner;
diff --git a/chrome/services/sharing/nearby/platform/condition_variable.h b/chrome/services/sharing/nearby/platform/condition_variable.h index 53547d3..16c27454 100644 --- a/chrome/services/sharing/nearby/platform/condition_variable.h +++ b/chrome/services/sharing/nearby/platform/condition_variable.h
@@ -7,7 +7,7 @@ #include "base/synchronization/condition_variable.h" #include "third_party/abseil-cpp/absl/time/time.h" -#include "third_party/nearby/src/cpp/platform/api/condition_variable.h" +#include "third_party/nearby/src/internal/platform/implementation/condition_variable.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/count_down_latch.h b/chrome/services/sharing/nearby/platform/count_down_latch.h index 50c3496..f1849fe 100644 --- a/chrome/services/sharing/nearby/platform/count_down_latch.h +++ b/chrome/services/sharing/nearby/platform/count_down_latch.h
@@ -8,7 +8,7 @@ #include "base/atomic_ref_count.h" #include "base/synchronization/waitable_event.h" #include "third_party/abseil-cpp/absl/time/time.h" -#include "third_party/nearby/src/cpp/platform/api/count_down_latch.h" +#include "third_party/nearby/src/internal/platform/implementation/count_down_latch.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/crypto.cc b/chrome/services/sharing/nearby/platform/crypto.cc index deebf125..c7cb055 100644 --- a/chrome/services/sharing/nearby/platform/crypto.cc +++ b/chrome/services/sharing/nearby/platform/crypto.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/nearby/src/cpp/platform/api/crypto.h" +#include "third_party/nearby/src/internal/platform/implementation/crypto.h" #include "base/hash/md5.h" #include "base/memory/ptr_util.h"
diff --git a/chrome/services/sharing/nearby/platform/crypto_unittest.cc b/chrome/services/sharing/nearby/platform/crypto_unittest.cc index 25d6d9d..ce035b0 100644 --- a/chrome/services/sharing/nearby/platform/crypto_unittest.cc +++ b/chrome/services/sharing/nearby/platform/crypto_unittest.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/nearby/src/cpp/platform/api/crypto.h" +#include "third_party/nearby/src/internal/platform/implementation/crypto.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/services/sharing/nearby/platform/input_file.h b/chrome/services/sharing/nearby/platform/input_file.h index 1d8b104..8fc3363 100644 --- a/chrome/services/sharing/nearby/platform/input_file.h +++ b/chrome/services/sharing/nearby/platform/input_file.h
@@ -6,7 +6,7 @@ #define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_INPUT_FILE_H_ #include "base/files/file.h" -#include "third_party/nearby/src/cpp/platform/api/input_file.h" +#include "third_party/nearby/src/internal/platform/implementation/input_file.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/input_stream_impl.cc b/chrome/services/sharing/nearby/platform/input_stream_impl.cc index e113283..cff32a5 100644 --- a/chrome/services/sharing/nearby/platform/input_stream_impl.cc +++ b/chrome/services/sharing/nearby/platform/input_stream_impl.cc
@@ -19,7 +19,8 @@ "Nearby.Connections.Bluetooth.Socket.Read.Result", success); break; case connections::mojom::Medium::kWifiLan: - // TODO(https://crbug.com/1261238): Record metric. + base::UmaHistogramBoolean("Nearby.Connections.WifiLan.Socket.Read.Result", + success); break; case connections::mojom::Medium::kUnknown: case connections::mojom::Medium::kMdns:
diff --git a/chrome/services/sharing/nearby/platform/input_stream_impl.h b/chrome/services/sharing/nearby/platform/input_stream_impl.h index 4a1c98b..ae426b1 100644 --- a/chrome/services/sharing/nearby/platform/input_stream_impl.h +++ b/chrome/services/sharing/nearby/platform/input_stream_impl.h
@@ -5,7 +5,7 @@ #ifndef CHROME_SERVICES_SHARING_NEARBY_PLATFORM_INPUT_STREAM_IMPL_H_ #define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_INPUT_STREAM_IMPL_H_ -#include "third_party/nearby/src/cpp/platform/base/input_stream.h" +#include "third_party/nearby/src/internal/platform/input_stream.h" #include <stdint.h> #include <memory>
diff --git a/chrome/services/sharing/nearby/platform/log_message.h b/chrome/services/sharing/nearby/platform/log_message.h index a0ce5170..75c9ce99 100644 --- a/chrome/services/sharing/nearby/platform/log_message.h +++ b/chrome/services/sharing/nearby/platform/log_message.h
@@ -6,7 +6,7 @@ #define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_LOG_MESSAGE_H_ #include "base/logging.h" -#include "third_party/nearby/src/cpp/platform/api/log_message.h" +#include "third_party/nearby/src/internal/platform/implementation/log_message.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/mutex.h b/chrome/services/sharing/nearby/platform/mutex.h index d57bcd8..c03df64 100644 --- a/chrome/services/sharing/nearby/platform/mutex.h +++ b/chrome/services/sharing/nearby/platform/mutex.h
@@ -6,7 +6,7 @@ #define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_MUTEX_H_ #include "base/synchronization/lock.h" -#include "third_party/nearby/src/cpp/platform/api/mutex.h" +#include "third_party/nearby/src/internal/platform/implementation/mutex.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/output_file.h b/chrome/services/sharing/nearby/platform/output_file.h index e7ef734f..0c0699ef 100644 --- a/chrome/services/sharing/nearby/platform/output_file.h +++ b/chrome/services/sharing/nearby/platform/output_file.h
@@ -6,7 +6,7 @@ #define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_OUTPUT_FILE_H_ #include "base/files/file.h" -#include "third_party/nearby/src/cpp/platform/api/output_file.h" +#include "third_party/nearby/src/internal/platform/implementation/output_file.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/output_stream_impl.cc b/chrome/services/sharing/nearby/platform/output_stream_impl.cc index 014322b..039cdd9c 100644 --- a/chrome/services/sharing/nearby/platform/output_stream_impl.cc +++ b/chrome/services/sharing/nearby/platform/output_stream_impl.cc
@@ -19,7 +19,8 @@ "Nearby.Connections.Bluetooth.Socket.Write.Result", success); break; case connections::mojom::Medium::kWifiLan: - // TODO(https://crbug.com/1261238): Record metric. + base::UmaHistogramBoolean( + "Nearby.Connections.WifiLan.Socket.Write.Result", success); break; case connections::mojom::Medium::kUnknown: case connections::mojom::Medium::kMdns:
diff --git a/chrome/services/sharing/nearby/platform/output_stream_impl.h b/chrome/services/sharing/nearby/platform/output_stream_impl.h index 3b3f497..3cd6659 100644 --- a/chrome/services/sharing/nearby/platform/output_stream_impl.h +++ b/chrome/services/sharing/nearby/platform/output_stream_impl.h
@@ -5,7 +5,7 @@ #ifndef CHROME_SERVICES_SHARING_NEARBY_PLATFORM_OUTPUT_STREAM_IMPL_H_ #define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_OUTPUT_STREAM_IMPL_H_ -#include "third_party/nearby/src/cpp/platform/base/output_stream.h" +#include "third_party/nearby/src/internal/platform/output_stream.h" #include <stdint.h> #include <memory>
diff --git a/chrome/services/sharing/nearby/platform/recursive_mutex.h b/chrome/services/sharing/nearby/platform/recursive_mutex.h index 3c75919..5e45777 100644 --- a/chrome/services/sharing/nearby/platform/recursive_mutex.h +++ b/chrome/services/sharing/nearby/platform/recursive_mutex.h
@@ -8,7 +8,7 @@ #include "base/synchronization/lock.h" #include "base/thread_annotations.h" #include "base/threading/platform_thread.h" -#include "third_party/nearby/src/cpp/platform/api/mutex.h" +#include "third_party/nearby/src/internal/platform/implementation/mutex.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/scheduled_executor.h b/chrome/services/sharing/nearby/platform/scheduled_executor.h index a5c54dce..76941a2 100644 --- a/chrome/services/sharing/nearby/platform/scheduled_executor.h +++ b/chrome/services/sharing/nearby/platform/scheduled_executor.h
@@ -16,7 +16,7 @@ #include "base/timer/timer.h" #include "base/unguessable_token.h" #include "third_party/abseil-cpp/absl/time/time.h" -#include "third_party/nearby/src/cpp/platform/api/scheduled_executor.h" +#include "third_party/nearby/src/internal/platform/implementation/scheduled_executor.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/submittable_executor.h b/chrome/services/sharing/nearby/platform/submittable_executor.h index a15f850..46e1046 100644 --- a/chrome/services/sharing/nearby/platform/submittable_executor.h +++ b/chrome/services/sharing/nearby/platform/submittable_executor.h
@@ -12,7 +12,7 @@ #include "base/task/task_runner.h" #include "base/thread_annotations.h" #include "chrome/services/sharing/nearby/platform/atomic_boolean.h" -#include "third_party/nearby/src/cpp/platform/api/submittable_executor.h" +#include "third_party/nearby/src/internal/platform/implementation/submittable_executor.h" namespace location { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/system_clock.cc b/chrome/services/sharing/nearby/platform/system_clock.cc index b0b0ca8..e3290d9 100644 --- a/chrome/services/sharing/nearby/platform/system_clock.cc +++ b/chrome/services/sharing/nearby/platform/system_clock.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "third_party/nearby/src/cpp/platform/api/system_clock.h" +#include "third_party/nearby/src/internal/platform/implementation/system_clock.h" #include "base/check_op.h" #include "base/threading/platform_thread.h"
diff --git a/chrome/services/sharing/nearby/platform/webrtc.cc b/chrome/services/sharing/nearby/platform/webrtc.cc index 67872dd..21d054f9 100644 --- a/chrome/services/sharing/nearby/platform/webrtc.cc +++ b/chrome/services/sharing/nearby/platform/webrtc.cc
@@ -14,9 +14,9 @@ #include "components/webrtc/thread_wrapper.h" #include "mojo/public/cpp/bindings/receiver.h" #include "mojo/public/cpp/bindings/self_owned_receiver.h" -#include "third_party/nearby/src/cpp/platform/public/count_down_latch.h" -#include "third_party/nearby/src/cpp/platform/public/future.h" -#include "third_party/nearby/src/cpp/platform/public/logging.h" +#include "third_party/nearby/src/internal/platform/count_down_latch.h" +#include "third_party/nearby/src/internal/platform/future.h" +#include "third_party/nearby/src/internal/platform/logging.h" #include "third_party/webrtc/api/jsep.h" #include "third_party/webrtc/api/peer_connection_interface.h" #include "third_party/webrtc_overrides/task_queue_factory.h"
diff --git a/chrome/services/sharing/nearby/platform/webrtc.h b/chrome/services/sharing/nearby/platform/webrtc.h index e674ae9..8ddbf50 100644 --- a/chrome/services/sharing/nearby/platform/webrtc.h +++ b/chrome/services/sharing/nearby/platform/webrtc.h
@@ -5,7 +5,7 @@ #ifndef CHROME_SERVICES_SHARING_NEARBY_PLATFORM_WEBRTC_H_ #define CHROME_SERVICES_SHARING_NEARBY_PLATFORM_WEBRTC_H_ -#include "third_party/nearby/src/cpp/platform/api/webrtc.h" +#include "third_party/nearby/src/internal/platform/implementation/webrtc.h" #include <memory>
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc b/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc index 26acaa5a..bfcbaf6a 100644 --- a/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc +++ b/chrome/services/sharing/nearby/platform/wifi_lan_medium.cc
@@ -129,8 +129,6 @@ return nullptr; } - VLOG(1) << "WifiLanMedium::" << __func__ << ": Connection established with " - << connected_socket_parameters->remote_end_point.ToString(); return std::make_unique<WifiLanSocket>( std::move(*connected_socket_parameters)); } @@ -187,7 +185,7 @@ VLOG(1) << "WifiLanMedium::" << __func__ << ": Created TCP connected socket. local_addr=" << local_addr->ToString() << ", peer_addr=" << peer_addr->ToString(); - *connected_socket_parameters = {*peer_addr, std::move(tcp_connected_socket), + *connected_socket_parameters = {std::move(tcp_connected_socket), std::move(receive_stream), std::move(send_stream)};
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_medium.h b/chrome/services/sharing/nearby/platform/wifi_lan_medium.h index a141719..0ea01a8 100644 --- a/chrome/services/sharing/nearby/platform/wifi_lan_medium.h +++ b/chrome/services/sharing/nearby/platform/wifi_lan_medium.h
@@ -23,7 +23,7 @@ #include "net/base/ip_endpoint.h" #include "services/network/public/mojom/tcp_socket.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/nearby/src/cpp/platform/api/wifi_lan.h" +#include "third_party/nearby/src/internal/platform/implementation/wifi_lan.h" namespace ash { namespace nearby {
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.cc b/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.cc index a077db6..0203be1 100644 --- a/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.cc +++ b/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.cc
@@ -131,7 +131,7 @@ DCHECK(remote_addr); VLOG(1) << "WifiLanServerSocket::" << __func__ << ": Connection accepted from " << remote_addr->ToString(); - *connected_socket_parameters = {*remote_addr, std::move(connected_socket), + *connected_socket_parameters = {std::move(connected_socket), std::move(receive_stream), std::move(send_stream)}; } else {
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.h b/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.h index a86820c..05b8a1c5 100644 --- a/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.h +++ b/chrome/services/sharing/nearby/platform/wifi_lan_server_socket.h
@@ -18,7 +18,7 @@ #include "net/base/ip_endpoint.h" #include "services/network/public/mojom/tcp_socket.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" -#include "third_party/nearby/src/cpp/platform/api/wifi_lan.h" +#include "third_party/nearby/src/internal/platform/implementation/wifi_lan.h" namespace base { class SequencedTaskRunner;
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_socket.cc b/chrome/services/sharing/nearby/platform/wifi_lan_socket.cc index 1f27696..df6f44c 100644 --- a/chrome/services/sharing/nearby/platform/wifi_lan_socket.cc +++ b/chrome/services/sharing/nearby/platform/wifi_lan_socket.cc
@@ -13,13 +13,11 @@ namespace chrome { WifiLanSocket::ConnectedSocketParameters::ConnectedSocketParameters( - const net::IPEndPoint& remote_end_point, mojo::PendingRemote<network::mojom::TCPConnectedSocket> tcp_connected_socket, mojo::ScopedDataPipeConsumerHandle receive_stream, mojo::ScopedDataPipeProducerHandle send_stream) - : remote_end_point(remote_end_point), - tcp_connected_socket(std::move(tcp_connected_socket)), + : tcp_connected_socket(std::move(tcp_connected_socket)), receive_stream(std::move(receive_stream)), send_stream(std::move(send_stream)) {} @@ -34,31 +32,23 @@ ConnectedSocketParameters&&) = default; WifiLanSocket::WifiLanSocket( - const net::IPEndPoint& remote_end_point, - mojo::PendingRemote<network::mojom::TCPConnectedSocket> - tcp_connected_socket, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream) + ConnectedSocketParameters connected_socket_parameters) : task_runner_( base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()})), - tcp_connected_socket_(std::move(tcp_connected_socket), task_runner_), - bidirectional_stream_(connections::mojom::Medium::kWifiLan, - task_runner_, - std::move(receive_stream), - std::move(send_stream)) { + tcp_connected_socket_( + std::move(connected_socket_parameters.tcp_connected_socket), + task_runner_), + bidirectional_stream_( + connections::mojom::Medium::kWifiLan, + task_runner_, + std::move(connected_socket_parameters.receive_stream), + std::move(connected_socket_parameters.send_stream)) { tcp_connected_socket_.set_disconnect_handler( base::BindOnce(&WifiLanSocket::OnTcpConnectedSocketDisconnected, base::Unretained(this)), task_runner_); } -WifiLanSocket::WifiLanSocket( - ConnectedSocketParameters connected_socket_parameters) - : WifiLanSocket(connected_socket_parameters.remote_end_point, - std::move(connected_socket_parameters.tcp_connected_socket), - std::move(connected_socket_parameters.receive_stream), - std::move(connected_socket_parameters.send_stream)) {} - WifiLanSocket::~WifiLanSocket() { Close(); }
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_socket.h b/chrome/services/sharing/nearby/platform/wifi_lan_socket.h index b06440675..f1303cc 100644 --- a/chrome/services/sharing/nearby/platform/wifi_lan_socket.h +++ b/chrome/services/sharing/nearby/platform/wifi_lan_socket.h
@@ -11,9 +11,8 @@ #include "mojo/public/cpp/bindings/pending_remote.h" #include "mojo/public/cpp/bindings/shared_remote.h" #include "mojo/public/cpp/system/data_pipe.h" -#include "net/base/ip_endpoint.h" #include "services/network/public/mojom/tcp_socket.mojom.h" -#include "third_party/nearby/src/cpp/platform/api/wifi_lan.h" +#include "third_party/nearby/src/internal/platform/implementation/wifi_lan.h" namespace base { class SequencedTaskRunner; @@ -31,7 +30,6 @@ // Parameters needed to construct a WifiLanSocket. struct ConnectedSocketParameters { ConnectedSocketParameters( - const net::IPEndPoint& remote_end_point, mojo::PendingRemote<network::mojom::TCPConnectedSocket> tcp_connected_socket, mojo::ScopedDataPipeConsumerHandle receive_stream, @@ -40,18 +38,12 @@ ConnectedSocketParameters(ConnectedSocketParameters&&); ConnectedSocketParameters& operator=(ConnectedSocketParameters&&); - net::IPEndPoint remote_end_point; mojo::PendingRemote<network::mojom::TCPConnectedSocket> tcp_connected_socket; mojo::ScopedDataPipeConsumerHandle receive_stream; mojo::ScopedDataPipeProducerHandle send_stream; }; - WifiLanSocket(const net::IPEndPoint& remote_end_point, - mojo::PendingRemote<network::mojom::TCPConnectedSocket> - tcp_connected_socket, - mojo::ScopedDataPipeConsumerHandle receive_stream, - mojo::ScopedDataPipeProducerHandle send_stream); explicit WifiLanSocket(ConnectedSocketParameters connected_socket_parameters); WifiLanSocket(const WifiLanSocket&) = delete; WifiLanSocket& operator=(const WifiLanSocket&) = delete;
diff --git a/chrome/services/sharing/nearby/platform/wifi_lan_socket_unittest.cc b/chrome/services/sharing/nearby/platform/wifi_lan_socket_unittest.cc index 486584d5..ae45b3df 100644 --- a/chrome/services/sharing/nearby/platform/wifi_lan_socket_unittest.cc +++ b/chrome/services/sharing/nearby/platform/wifi_lan_socket_unittest.cc
@@ -18,12 +18,6 @@ namespace nearby { namespace chrome { -namespace { - -const net::IPEndPoint kRemoteAddress(net::IPAddress(192, 168, 86, 62), 33333); - -} // namespace - class WifiLanSocketTest : public ::testing::Test { public: WifiLanSocketTest() = default; @@ -56,9 +50,10 @@ tcp_connected_socket.InitWithNewPipeAndPassReceiver()); wifi_lan_socket_ = std::make_unique<WifiLanSocket>( - kRemoteAddress, std::move(tcp_connected_socket), - std::move(receive_pipe_consumer_handle), - std::move(send_pipe_producer_handle)); + WifiLanSocket::ConnectedSocketParameters( + std::move(tcp_connected_socket), + std::move(receive_pipe_consumer_handle), + std::move(send_pipe_producer_handle))); } void TearDown() override { wifi_lan_socket_.reset(); }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 8c442b00..67cb28e 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -6076,6 +6076,7 @@ # GCMDriverAndroid is not yet implemented. "../browser/gcm/gcm_profile_service_unittest.cc", "../browser/hid/hid_chooser_context_unittest.cc", + "../browser/hid/hid_policy_allowed_devices_unittest.cc", "../browser/importer/profile_writer_unittest.cc", "../browser/lifetime/application_lifetime_unittest.cc", "../browser/lookalikes/lookalike_url_navigation_throttle_unittest.cc", @@ -8792,6 +8793,7 @@ "../browser/ui/views/user_education/help_bubble_factory_views_interactive_uitest.cc", "../browser/ui/views/user_education/help_bubble_view_interactive_uitest.cc", "../browser/ui/views/user_education/interaction_sequence_interactive_uitest.cc", + "../browser/ui/views/user_education/tutorial_interactive_uitest.cc", ] deps += [ "//components/optimization_guide/core:test_support",
diff --git a/chrome/test/base/testing_browser_process.cc b/chrome/test/base/testing_browser_process.cc index 66023194..e655aa85 100644 --- a/chrome/test/base/testing_browser_process.cc +++ b/chrome/test/base/testing_browser_process.cc
@@ -62,6 +62,7 @@ #endif #if !BUILDFLAG(IS_ANDROID) +#include "chrome/browser/hid/hid_policy_allowed_devices.h" #include "chrome/browser/serial/serial_policy_allowed_ports.h" #include "components/keep_alive_registry/keep_alive_registry.h" #endif @@ -437,6 +438,14 @@ } return serial_policy_allowed_ports_.get(); } + +HidPolicyAllowedDevices* TestingBrowserProcess::hid_policy_allowed_devices() { + if (!hid_policy_allowed_devices_) { + hid_policy_allowed_devices_ = + std::make_unique<HidPolicyAllowedDevices>(local_state()); + } + return hid_policy_allowed_devices_.get(); +} #endif BuildState* TestingBrowserProcess::GetBuildState() { @@ -490,6 +499,7 @@ #endif #if !BUILDFLAG(IS_ANDROID) serial_policy_allowed_ports_.reset(); + hid_policy_allowed_devices_.reset(); #endif ShutdownBrowserPolicyConnector(); created_browser_policy_connector_ = false;
diff --git a/chrome/test/base/testing_browser_process.h b/chrome/test/base/testing_browser_process.h index ecada662..0d2454c 100644 --- a/chrome/test/base/testing_browser_process.h +++ b/chrome/test/base/testing_browser_process.h
@@ -144,6 +144,7 @@ override; #if !BUILDFLAG(IS_ANDROID) SerialPolicyAllowedPorts* serial_policy_allowed_ports() override; + HidPolicyAllowedDevices* hid_policy_allowed_devices() override; #endif BuildState* GetBuildState() override; breadcrumbs::BreadcrumbPersistentStorageManager* @@ -231,6 +232,7 @@ #if !BUILDFLAG(IS_ANDROID) std::unique_ptr<SerialPolicyAllowedPorts> serial_policy_allowed_ports_; + std::unique_ptr<HidPolicyAllowedDevices> hid_policy_allowed_devices_; BuildState build_state_; #endif };
diff --git a/chrome/test/chromedriver/keycode_text_conversion_x.cc b/chrome/test/chromedriver/keycode_text_conversion_x.cc index e1e7733..5108681 100644 --- a/chrome/test/chromedriver/keycode_text_conversion_x.cc +++ b/chrome/test/chromedriver/keycode_text_conversion_x.cc
@@ -172,7 +172,7 @@ } key_event.state = state; key_event.opcode = x11::KeyEvent::Press; - x11::Event event(std::move(key_event)); + x11::Event event(false, std::move(key_event)); uint16_t character = ui::GetCharacterFromXEvent(event); if (!character)
diff --git a/chrome/test/chromedriver/util.cc b/chrome/test/chromedriver/util.cc index 3541050..194b6e19 100644 --- a/chrome/test/chromedriver/util.cc +++ b/chrome/test/chromedriver/util.cc
@@ -528,8 +528,22 @@ base::StringPiece path, std::string* out_value, bool* has_value) { - return GetOptionalValueDeprecated(dict, path, out_value, has_value, - &base::Value::GetAsString); + if (has_value != nullptr) + *has_value = false; + + if (!dict->is_dict()) + return false; + + const base::Value* value = dict->FindPath(path); + if (!value) + return true; + if (value->is_string()) { + *out_value = value->GetString(); + if (has_value != nullptr) + *has_value = true; + return true; + } + return false; } bool GetOptionalDictionary(const base::DictionaryValue* dict,
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_cross_origin_iframe_with_ot_request.html b/chrome/test/data/client_hints/accept_ch_ua_cross_origin_iframe_with_ot_request.html similarity index 100% rename from chrome/test/data/client_hints/accept_ch_ua_reduced_cross_origin_iframe_with_ot_request.html rename to chrome/test/data/client_hints/accept_ch_ua_cross_origin_iframe_with_ot_request.html
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_cross_origin_iframe_with_subrequests.html b/chrome/test/data/client_hints/accept_ch_ua_cross_origin_iframe_with_subrequests.html similarity index 100% rename from chrome/test/data/client_hints/accept_ch_ua_reduced_cross_origin_iframe_with_subrequests.html rename to chrome/test/data/client_hints/accept_ch_ua_cross_origin_iframe_with_subrequests.html
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_iframe_request.html b/chrome/test/data/client_hints/accept_ch_ua_iframe_request.html similarity index 100% rename from chrome/test/data/client_hints/accept_ch_ua_reduced_iframe_request.html rename to chrome/test/data/client_hints/accept_ch_ua_iframe_request.html
diff --git a/chrome/test/data/client_hints/accept_ch_ua_missing_valid_origin_trial.html b/chrome/test/data/client_hints/accept_ch_ua_missing_valid_origin_trial.html new file mode 100644 index 0000000..e7910474 --- /dev/null +++ b/chrome/test/data/client_hints/accept_ch_ua_missing_valid_origin_trial.html
@@ -0,0 +1,5 @@ +<html> +<link rel="icon" href="data:;base64,="> +<head></head> +The Origin Trial token is valid, but the Sec-CH-UA-Reduced or Sec-CH-UA-Full header is not present. +</html>
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_cross_origin_iframe_with_ot_request.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_ua_reduced_cross_origin_iframe_with_ot_request.html.mock-http-headers deleted file mode 100644 index 86875f7..0000000 --- a/chrome/test/data/client_hints/accept_ch_ua_reduced_cross_origin_iframe_with_ot_request.html.mock-http-headers +++ /dev/null
@@ -1,2 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html; charset=utf-8
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_cross_origin_iframe_with_subrequests.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_ua_reduced_cross_origin_iframe_with_subrequests.html.mock-http-headers deleted file mode 100644 index 86875f7..0000000 --- a/chrome/test/data/client_hints/accept_ch_ua_reduced_cross_origin_iframe_with_subrequests.html.mock-http-headers +++ /dev/null
@@ -1,2 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html; charset=utf-8
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_iframe_request.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_ua_reduced_iframe_request.html.mock-http-headers deleted file mode 100644 index bf286b0f..0000000 --- a/chrome/test/data/client_hints/accept_ch_ua_reduced_iframe_request.html.mock-http-headers +++ /dev/null
@@ -1,4 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-reduced -Origin-Trial: A93QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_missing_valid_origin_trial.html b/chrome/test/data/client_hints/accept_ch_ua_reduced_missing_valid_origin_trial.html deleted file mode 100644 index c340ceb..0000000 --- a/chrome/test/data/client_hints/accept_ch_ua_reduced_missing_valid_origin_trial.html +++ /dev/null
@@ -1,5 +0,0 @@ -<html> -<link rel="icon" href="data:;base64,="> -<head></head> -The Origin Trial token is valid, but the Sec-CH-UA-Reduced header is not present. -</html>
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_missing_valid_origin_trial.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_ua_reduced_missing_valid_origin_trial.html.mock-http-headers deleted file mode 100644 index 00c98741..0000000 --- a/chrome/test/data/client_hints/accept_ch_ua_reduced_missing_valid_origin_trial.html.mock-http-headers +++ /dev/null
@@ -1,4 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-full-version -Origin-Trial: A93QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_subresource_request.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_ua_reduced_subresource_request.html.mock-http-headers deleted file mode 100644 index bf286b0f..0000000 --- a/chrome/test/data/client_hints/accept_ch_ua_reduced_subresource_request.html.mock-http-headers +++ /dev/null
@@ -1,4 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-reduced -Origin-Trial: A93QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_with_invalid_origin_trial.html b/chrome/test/data/client_hints/accept_ch_ua_reduced_with_invalid_origin_trial.html deleted file mode 100644 index 9b8fc9e..0000000 --- a/chrome/test/data/client_hints/accept_ch_ua_reduced_with_invalid_origin_trial.html +++ /dev/null
@@ -1,9 +0,0 @@ -<html> -<link rel="icon" href="data:;base64,="> -<head> -<link rel="stylesheet" href="style.css"> -</head> -Empty file which uses link-rel to disable favicon fetches. The corresponding -.mock-http-headers sets client hints. The Origin Trial token in the headers -file is a corruption of the valid Origin Trial token. -</html>
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_with_invalid_origin_trial.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_ua_reduced_with_invalid_origin_trial.html.mock-http-headers deleted file mode 100644 index f9543f9..0000000 --- a/chrome/test/data/client_hints/accept_ch_ua_reduced_with_invalid_origin_trial.html.mock-http-headers +++ /dev/null
@@ -1,4 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-full-version,sec-ch-ua-reduced -Origin-Trial: A23QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJvcmlnbW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_with_no_origin_trial.html b/chrome/test/data/client_hints/accept_ch_ua_reduced_with_no_origin_trial.html deleted file mode 100644 index 8988d58..0000000 --- a/chrome/test/data/client_hints/accept_ch_ua_reduced_with_no_origin_trial.html +++ /dev/null
@@ -1,8 +0,0 @@ -<html> -<link rel="icon" href="data:;base64,="> -<head></head> -Empty file which uses link-rel to disable favicon fetches. The corresponding -.mock-http-headers sets client hints. The Origin Trial token in the headers -file is missing, even though the Sec-CH-UA-Reduced client hint is present in -the Accept-CH header. -</html>
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_with_no_origin_trial.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_ua_reduced_with_no_origin_trial.html.mock-http-headers deleted file mode 100644 index ec93464..0000000 --- a/chrome/test/data/client_hints/accept_ch_ua_reduced_with_no_origin_trial.html.mock-http-headers +++ /dev/null
@@ -1,3 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-full-version,sec-ch-ua-reduced
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_with_valid_origin_trial.html.mock-http-headers b/chrome/test/data/client_hints/accept_ch_ua_reduced_with_valid_origin_trial.html.mock-http-headers deleted file mode 100644 index 1d3bf6e..0000000 --- a/chrome/test/data/client_hints/accept_ch_ua_reduced_with_valid_origin_trial.html.mock-http-headers +++ /dev/null
@@ -1,4 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-full-version,sec-ch-ua-reduced -Origin-Trial: A93QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_subresource_request.html b/chrome/test/data/client_hints/accept_ch_ua_subresource_request.html similarity index 100% rename from chrome/test/data/client_hints/accept_ch_ua_reduced_subresource_request.html rename to chrome/test/data/client_hints/accept_ch_ua_subresource_request.html
diff --git a/chrome/test/data/client_hints/accept_ch_ua_with_invalid_origin_trial.html b/chrome/test/data/client_hints/accept_ch_ua_with_invalid_origin_trial.html new file mode 100644 index 0000000..94bbaa0 --- /dev/null +++ b/chrome/test/data/client_hints/accept_ch_ua_with_invalid_origin_trial.html
@@ -0,0 +1,8 @@ +<html> +<link rel="icon" href="data:;base64,="> +<head> +<link rel="stylesheet" href="style.css"> +</head> +Empty file which uses link-rel to disable favicon fetches. The Origin Trial token in the headers +file is a corruption of the valid Origin Trial token. +</html>
diff --git a/chrome/test/data/client_hints/accept_ch_ua_with_no_origin_trial.html b/chrome/test/data/client_hints/accept_ch_ua_with_no_origin_trial.html new file mode 100644 index 0000000..f88e320 --- /dev/null +++ b/chrome/test/data/client_hints/accept_ch_ua_with_no_origin_trial.html
@@ -0,0 +1,7 @@ +<html> +<link rel="icon" href="data:;base64,="> +<head></head> +Empty file which uses link-rel to disable favicon fetches. The Origin Trial token in the headers +file is missing, even though the Sec-CH-UA-Reduced or Sec-CH-UA-Full client hint is present in +the Accept-CH header. +</html>
diff --git a/chrome/test/data/client_hints/accept_ch_ua_with_valid_origin_trial.html b/chrome/test/data/client_hints/accept_ch_ua_with_valid_origin_trial.html new file mode 100644 index 0000000..1123e58 --- /dev/null +++ b/chrome/test/data/client_hints/accept_ch_ua_with_valid_origin_trial.html
@@ -0,0 +1,8 @@ +<html> +<link rel="icon" href="data:;base64,="> +<head></head> +Empty file which uses link-rel to disable favicon fetches. +The Origin Trial token was generated by running (in tools/origin_trials): +generate_token.py https://127.0.0.1:44444 UserAgentReduction --expire-timestamp=2000000000 +generate_token.py https://127.0.0.1:44444 SendFullUserAgentAfterReduction --expire-timestamp=2000000000 +</html>
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_iframe_request.html b/chrome/test/data/client_hints/critical_ch_ua_iframe_request.html similarity index 100% copy from chrome/test/data/client_hints/accept_ch_ua_reduced_iframe_request.html copy to chrome/test/data/client_hints/critical_ch_ua_iframe_request.html
diff --git a/chrome/test/data/client_hints/critical_ch_ua_reduced_iframe_request.html b/chrome/test/data/client_hints/critical_ch_ua_reduced_iframe_request.html deleted file mode 100644 index e394e26..0000000 --- a/chrome/test/data/client_hints/critical_ch_ua_reduced_iframe_request.html +++ /dev/null
@@ -1,7 +0,0 @@ -<html> -<link rel="icon" href="data:;base64,="> -<head></head> -<body> -<iframe src="simple.html" id="test"></iframe> -</body> -</html>
diff --git a/chrome/test/data/client_hints/critical_ch_ua_reduced_iframe_request.html.mock-http-headers b/chrome/test/data/client_hints/critical_ch_ua_reduced_iframe_request.html.mock-http-headers deleted file mode 100644 index 3e20297..0000000 --- a/chrome/test/data/client_hints/critical_ch_ua_reduced_iframe_request.html.mock-http-headers +++ /dev/null
@@ -1,5 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-reduced -Critical-CH: sec-ch-ua-reduced -Origin-Trial: A93QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/critical_ch_ua_reduced_subresource_request.html b/chrome/test/data/client_hints/critical_ch_ua_reduced_subresource_request.html deleted file mode 100644 index 9d24aa6..0000000 --- a/chrome/test/data/client_hints/critical_ch_ua_reduced_subresource_request.html +++ /dev/null
@@ -1,7 +0,0 @@ -<html> -<link rel="icon" href="data:;base64,="> -<head> -<link rel="stylesheet" href="style.css"> -</head> -<body></body> -</html>
diff --git a/chrome/test/data/client_hints/critical_ch_ua_reduced_subresource_request.html.mock-http-headers b/chrome/test/data/client_hints/critical_ch_ua_reduced_subresource_request.html.mock-http-headers deleted file mode 100644 index 3e20297..0000000 --- a/chrome/test/data/client_hints/critical_ch_ua_reduced_subresource_request.html.mock-http-headers +++ /dev/null
@@ -1,5 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-reduced -Critical-CH: sec-ch-ua-reduced -Origin-Trial: A93QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/critical_ch_ua_reduced_with_invalid_origin_trial.html b/chrome/test/data/client_hints/critical_ch_ua_reduced_with_invalid_origin_trial.html deleted file mode 100644 index 9666ba7..0000000 --- a/chrome/test/data/client_hints/critical_ch_ua_reduced_with_invalid_origin_trial.html +++ /dev/null
@@ -1,7 +0,0 @@ -<html> -<link rel="icon" href="data:;base64,="> -<head></head> -Empty file which uses link-rel to disable favicon fetches. The corresponding -.mock-http-headers sets client hints. The Origin Trial token is a corrupted -version of the original. -</html>
diff --git a/chrome/test/data/client_hints/critical_ch_ua_reduced_with_invalid_origin_trial.html.mock-http-headers b/chrome/test/data/client_hints/critical_ch_ua_reduced_with_invalid_origin_trial.html.mock-http-headers deleted file mode 100644 index 8452ef6..0000000 --- a/chrome/test/data/client_hints/critical_ch_ua_reduced_with_invalid_origin_trial.html.mock-http-headers +++ /dev/null
@@ -1,5 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-full-version,sec-ch-ua-reduced -Critical-CH: sec-ch-ua-reduced -Origin-Trial: A23QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+YS7dkQEWVfW9Ua2pTnA866sZwRzsElkPwsUdGdIaW0fRUP8AwAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/critical_ch_ua_reduced_with_valid_origin_trial.html b/chrome/test/data/client_hints/critical_ch_ua_reduced_with_valid_origin_trial.html deleted file mode 100644 index db1b984..0000000 --- a/chrome/test/data/client_hints/critical_ch_ua_reduced_with_valid_origin_trial.html +++ /dev/null
@@ -1,8 +0,0 @@ -<html> -<link rel="icon" href="data:;base64,="> -<head></head> -Empty file which uses link-rel to disable favicon fetches. The corresponding -.mock-http-headers sets client hints. The Origin Trial token was generated by -running (in tools/origin_trials): -generate_token.py https://127.0.0.1:44444 UserAgentReduction --expire-timestamp=2000000000 -</html>
diff --git a/chrome/test/data/client_hints/critical_ch_ua_reduced_with_valid_origin_trial.html.mock-http-headers b/chrome/test/data/client_hints/critical_ch_ua_reduced_with_valid_origin_trial.html.mock-http-headers deleted file mode 100644 index 426c2fd..0000000 --- a/chrome/test/data/client_hints/critical_ch_ua_reduced_with_valid_origin_trial.html.mock-http-headers +++ /dev/null
@@ -1,5 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-full-version,sec-ch-ua-reduced -Critical-CH: sec-ch-ua-reduced -Origin-Trial: A93QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_subresource_request.html b/chrome/test/data/client_hints/critical_ch_ua_subresource_request.html similarity index 100% copy from chrome/test/data/client_hints/accept_ch_ua_reduced_subresource_request.html copy to chrome/test/data/client_hints/critical_ch_ua_subresource_request.html
diff --git a/chrome/test/data/client_hints/critical_ch_ua_with_invalid_origin_trial.html b/chrome/test/data/client_hints/critical_ch_ua_with_invalid_origin_trial.html new file mode 100644 index 0000000..572da0d --- /dev/null +++ b/chrome/test/data/client_hints/critical_ch_ua_with_invalid_origin_trial.html
@@ -0,0 +1,6 @@ +<html> +<link rel="icon" href="data:;base64,="> +<head></head> +Empty file which uses link-rel to disable favicon fetches. The Origin Trial token is a corrupted +version of the original. +</html>
diff --git a/chrome/test/data/client_hints/accept_ch_ua_reduced_with_valid_origin_trial.html b/chrome/test/data/client_hints/critical_ch_ua_with_valid_origin_trial.html similarity index 100% rename from chrome/test/data/client_hints/accept_ch_ua_reduced_with_valid_origin_trial.html rename to chrome/test/data/client_hints/critical_ch_ua_with_valid_origin_trial.html
diff --git a/chrome/test/data/client_hints/frame_3p_ot.html.mock-http-headers b/chrome/test/data/client_hints/frame_3p_ot.html.mock-http-headers deleted file mode 100644 index 1f03679..0000000 --- a/chrome/test/data/client_hints/frame_3p_ot.html.mock-http-headers +++ /dev/null
@@ -1,4 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-reduced -Origin-Trial: Awgc/axBbE+4mDB+z2AKFEl26TUKBzCM2GBkDQmt4IephJgHpel1kcsIdCCBYKUgJ4s4+JQLXFKkOCs7lFIISAMAAAB0eyJvcmlnaW4iOiAiaHR0cHM6Ly9teS1zaXRlLmNvbTo0NDQ0NCIsICJpc1RoaXJkUGFydHkiOiB0cnVlLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/simple_3p_ot.html.mock-http-headers b/chrome/test/data/client_hints/simple_3p_ot.html.mock-http-headers deleted file mode 100644 index 1f03679..0000000 --- a/chrome/test/data/client_hints/simple_3p_ot.html.mock-http-headers +++ /dev/null
@@ -1,4 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-reduced -Origin-Trial: Awgc/axBbE+4mDB+z2AKFEl26TUKBzCM2GBkDQmt4IephJgHpel1kcsIdCCBYKUgJ4s4+JQLXFKkOCs7lFIISAMAAAB0eyJvcmlnaW4iOiAiaHR0cHM6Ly9teS1zaXRlLmNvbTo0NDQ0NCIsICJpc1RoaXJkUGFydHkiOiB0cnVlLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/subresource_redirect.html.mock-http-headers b/chrome/test/data/client_hints/subresource_redirect.html.mock-http-headers deleted file mode 100644 index 1f03679..0000000 --- a/chrome/test/data/client_hints/subresource_redirect.html.mock-http-headers +++ /dev/null
@@ -1,4 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html -Accept-CH: sec-ch-ua-reduced -Origin-Trial: Awgc/axBbE+4mDB+z2AKFEl26TUKBzCM2GBkDQmt4IephJgHpel1kcsIdCCBYKUgJ4s4+JQLXFKkOCs7lFIISAMAAAB0eyJvcmlnaW4iOiAiaHR0cHM6Ly9teS1zaXRlLmNvbTo0NDQ0NCIsICJpc1RoaXJkUGFydHkiOiB0cnVlLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0=
diff --git a/chrome/test/data/client_hints/top_level_with_iframe_redirect.html.mock-http-headers b/chrome/test/data/client_hints/top_level_with_iframe_redirect.html.mock-http-headers deleted file mode 100644 index 524e3d8c..0000000 --- a/chrome/test/data/client_hints/top_level_with_iframe_redirect.html.mock-http-headers +++ /dev/null
@@ -1,2 +0,0 @@ -HTTP/1.1 200 OK -Content-Type: text/html
diff --git a/chrome/test/data/webui/BUILD.gn b/chrome/test/data/webui/BUILD.gn index 0a35f78..7d4b2de2 100644 --- a/chrome/test/data/webui/BUILD.gn +++ b/chrome/test/data/webui/BUILD.gn
@@ -350,6 +350,7 @@ "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_bluetooth_summary_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_bluetooth_devices_subpage_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_bluetooth_device_detail_subpage_tests.m.js", + "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_bluetooth_true_wireless_images_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_bluetooth_change_device_name_dialog_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_paired_bluetooth_list_tests.m.js", "$root_gen_dir/chrome/test/data/webui/settings/chromeos/os_paired_bluetooth_list_item_tests.m.js",
diff --git a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_browsertest.js b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_browsertest.js index 0c84df2..175c3ea 100644 --- a/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_browsertest.js +++ b/chrome/test/data/webui/chromeos/emoji_picker/emoji_picker_browsertest.js
@@ -22,11 +22,7 @@ /** @override */ get featureList() { - return { - enabled: - ['chromeos::features::kImeSystemEmojiPicker,' + - 'chromeos::features::kImeSystemEmojiPickerClipboard'] - }; + return {enabled: ['chromeos::features::kImeSystemEmojiPickerClipboard']}; } }
diff --git a/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts index 153b3bd..c29d338 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_by_album_id_element_test.ts
@@ -140,4 +140,45 @@ await waitAfterNextRender(googlePhotosPhotosByAlbumIdElement); assertEquals(querySelectorAll(photoSelector)!.length, 0); }); + + test('selects photo', async () => { + personalizationStore.setReducersEnabled(true); + + const photo: GooglePhotosPhoto = { + id: '9bd1d7a3-f995-4445-be47-53c5b58ce1cb', + date: {data: []}, + url: {url: 'foo.com'} + }; + + // Initialize Google Photos data in the |personalizationStore|. + personalizationStore.data.wallpaper.googlePhotos.photosByAlbumId = { + '1': [photo] + }; + + // Initiallize |googlePhotosPhotosByAlbumIdElement|. + googlePhotosPhotosByAlbumIdElement = + initElement(GooglePhotosPhotosByAlbumId, {hidden: false}); + googlePhotosPhotosByAlbumIdElement.setAttribute('album-id', '1'); + await waitAfterNextRender(googlePhotosPhotosByAlbumIdElement); + + // Verify that the expected |photo| is rendered. + const photoSelector = 'wallpaper-grid-item:not([hidden]).photo'; + const photoEls = querySelectorAll(photoSelector) as WallpaperGridItem[]; + assertEquals(photoEls.length, 1); + assertEquals(photoEls[0]!.imageSrc, photo.url.url); + assertEquals(photoEls[0]!.primaryText, undefined); + assertEquals(photoEls[0]!.secondaryText, undefined); + + // Select |photo| and verify selection started. + photoEls[0]!.click(); + assertEquals(personalizationStore.data.wallpaper.loading.setImage, 1); + assertEquals(personalizationStore.data.wallpaper.loading.selected, true); + assertEquals(personalizationStore.data.wallpaper.pendingSelected, photo); + + // Wait for and verify hard-coded selection failure. + await new Promise(resolve => setTimeout(resolve, 1000)); + assertEquals(personalizationStore.data.wallpaper.loading.setImage, 0); + assertEquals(personalizationStore.data.wallpaper.loading.selected, false); + assertEquals(personalizationStore.data.wallpaper.pendingSelected, null); + }); }
diff --git a/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_element_test.ts index 592be4fa..081b7741 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/google_photos_photos_element_test.ts
@@ -83,10 +83,50 @@ // Verify that the expected |photos| are rendered. const photoEls = querySelectorAll(photoSelector) as WallpaperGridItem[]; assertEquals(photoEls.length, photos.length); - photoEls.forEach((albumEl, i) => { - assertEquals(albumEl.imageSrc, photos[i]!.url.url); - assertEquals(albumEl.primaryText, undefined); - assertEquals(albumEl.secondaryText, undefined); + photoEls.forEach((photoEl, i) => { + assertEquals(photoEl.imageSrc, photos[i]!.url.url); + assertEquals(photoEl.primaryText, undefined); + assertEquals(photoEl.secondaryText, undefined); }); }); + + test('selects photo', async () => { + const photo: GooglePhotosPhoto = { + id: '9bd1d7a3-f995-4445-be47-53c5b58ce1cb', + date: {data: []}, + url: {url: 'foo.com'} + }; + + // Set values returned by |wallpaperProvider|. + wallpaperProvider.setGooglePhotosPhotos([photo]); + wallpaperProvider.setGooglePhotosCount(1); + + // Initialize Google Photos data in the |personalizationStore|. + await initializeGooglePhotosData(wallpaperProvider, personalizationStore); + + // Initialize |googlePhotosPhotosElement|. + googlePhotosPhotosElement = + initElement(GooglePhotosPhotos, {hidden: false}); + await waitAfterNextRender(googlePhotosPhotosElement); + + // Verify that the expected |photo| is rendered. + const photoSelector = 'wallpaper-grid-item:not([hidden]).photo'; + const photoEls = querySelectorAll(photoSelector) as WallpaperGridItem[]; + assertEquals(photoEls.length, 1); + assertEquals(photoEls[0]!.imageSrc, photo.url.url); + assertEquals(photoEls[0]!.primaryText, undefined); + assertEquals(photoEls[0]!.secondaryText, undefined); + + // Select |photo| and verify selection started. + photoEls[0]!.click(); + assertEquals(personalizationStore.data.wallpaper.loading.setImage, 1); + assertEquals(personalizationStore.data.wallpaper.loading.selected, true); + assertEquals(personalizationStore.data.wallpaper.pendingSelected, photo); + + // Wait for and verify hard-coded selection failure. + await new Promise(resolve => setTimeout(resolve, 1000)); + assertEquals(personalizationStore.data.wallpaper.loading.setImage, 0); + assertEquals(personalizationStore.data.wallpaper.loading.selected, false); + assertEquals(personalizationStore.data.wallpaper.pendingSelected, null); + }); }
diff --git a/chrome/test/data/webui/chromeos/personalization_app/personalization_main_element_test.ts b/chrome/test/data/webui/chromeos/personalization_app/personalization_main_element_test.ts index 0e379d0c..84433e56 100644 --- a/chrome/test/data/webui/chromeos/personalization_app/personalization_main_element_test.ts +++ b/chrome/test/data/webui/chromeos/personalization_app/personalization_main_element_test.ts
@@ -18,13 +18,6 @@ personalizationMainElement = null; }); - test('displays content', async () => { - personalizationMainElement = initElement(PersonalizationMain); - assertEquals( - 'Personalization', - personalizationMainElement.shadowRoot!.querySelector('h1')!.innerText); - }); - test('links to user subpage', async () => { personalizationMainElement = initElement(PersonalizationMain); const original = PersonalizationRouter.instance;
diff --git a/chrome/test/data/webui/extensions/runtime_host_permissions_test.ts b/chrome/test/data/webui/extensions/runtime_host_permissions_test.ts index cb54cde..567782e 100644 --- a/chrome/test/data/webui/extensions/runtime_host_permissions_test.ts +++ b/chrome/test/data/webui/extensions/runtime_host_permissions_test.ts
@@ -477,4 +477,69 @@ assertEquals('https://chromium.org', args[1] /* site */); }); }); + + test( + 'switching away from ON_SPECIFIC_SITES with flag enabled triggers dialog', + function() { + element.enableEnhancedSiteControls = true; + + const permissions: chrome.developerPrivate.RuntimeHostPermissions = { + hostAccess: HostAccess.ON_SPECIFIC_SITES, + hasAllHosts: true, + hosts: [ + {host: 'https://example.com', granted: true}, + {host: 'https://chromium.org', granted: true}, + {host: '*://*.com/*', granted: false}, + ], + }; + + element.permissions = permissions; + flush(); + + const selectHostAccess = element.getSelectMenu(); + assertTrue(!!selectHostAccess); + + // Change the `selectHostAccess` value and the dialog should be open. + selectHostAccess.value = HostAccess.ON_CLICK; + selectHostAccess.dispatchEvent(new CustomEvent('change')); + flush(); + + let dialog = element.getRemoveSiteDialog(); + assertTrue(!!dialog); + assertTrue(dialog.open); + + // Clicking cancel on the dialog should revert the `selectHostAccess` + // value back to ON_SPECIFIC_SITES. + const cancel = dialog.querySelector<HTMLElement>('.cancel-button'); + assertTrue(!!cancel); + cancel.click(); + + flush(); + assertFalse(!!element.getRemoveSiteDialog()); + assertEquals(HostAccess.ON_SPECIFIC_SITES, selectHostAccess.value); + + // Change the `selectHostAccess` value and the dialog should be open. + selectHostAccess.value = HostAccess.ON_CLICK; + selectHostAccess.dispatchEvent(new CustomEvent('change')); + flush(); + + dialog = element.getRemoveSiteDialog(); + assertTrue(!!dialog); + assertTrue(dialog.open); + + // Clicking remove on the dialog should a call to the delegate to set + // the host access to the `selectHostAccess` value. + const remove = dialog.querySelector<HTMLElement>('.action-button'); + assertTrue(!!remove); + remove.click(); + + return delegate.whenCalled('setItemHostAccess').then((args) => { + assertEquals(ITEM_ID, args[0] /* id */); + assertEquals(HostAccess.ON_CLICK, args[1] /* access */); + + flush(); + assertFalse(!!element.getRemoveSiteDialog()); + assertEquals(HostAccess.ON_CLICK, selectHostAccess.value); + }); + }); });
diff --git a/chrome/test/data/webui/new_tab_page/BUILD.gn b/chrome/test/data/webui/new_tab_page/BUILD.gn index ecce2c78..273e1c3 100644 --- a/chrome/test/data/webui/new_tab_page/BUILD.gn +++ b/chrome/test/data/webui/new_tab_page/BUILD.gn
@@ -41,7 +41,7 @@ out_dir = "$target_gen_dir/tsc" tsconfig_base = "tsconfig_base.json" path_mappings = [ - "chrome://new_tab_page/*|" + + "chrome://new-tab-page/*|" + rebase_path("$root_gen_dir/chrome/browser/resources/new_tab_page/tsc/*", target_gen_dir), "chrome://webui-test/*|" +
diff --git a/chrome/test/data/webui/new_tab_page/realbox/realbox.gni b/chrome/test/data/webui/new_tab_page/realbox/realbox.gni index 2355a8c..aebc2ad 100644 --- a/chrome/test/data/webui/new_tab_page/realbox/realbox.gni +++ b/chrome/test/data/webui/new_tab_page/realbox/realbox.gni
@@ -2,4 +2,7 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -realbox_test_files = [ "realbox/realbox_test.js" ] +realbox_test_files = [ + "realbox/realbox_test.ts", + "realbox/test_realbox_browser_proxy.ts", +]
diff --git a/chrome/test/data/webui/new_tab_page/realbox/realbox_test.js b/chrome/test/data/webui/new_tab_page/realbox/realbox_test.ts similarity index 83% rename from chrome/test/data/webui/new_tab_page/realbox/realbox_test.js rename to chrome/test/data/webui/new_tab_page/realbox/realbox_test.ts index fecff83..2822da6 100644 --- a/chrome/test/data/webui/new_tab_page/realbox/realbox_test.js +++ b/chrome/test/data/webui/new_tab_page/realbox/realbox_test.ts
@@ -3,130 +3,29 @@ // found in the LICENSE file. import 'chrome://webui-test/mojo_webui_test_support.js'; +import 'chrome://new-tab-page/new_tab_page.js'; -import {$$, decodeString16, mojoString16, RealboxBrowserProxy} from 'chrome://new-tab-page/new_tab_page.js'; -import {PageCallbackRouter, PageHandlerRemote} from 'chrome://new-tab-page/realbox.mojom-webui.js'; +import {$$, decodeString16, mojoString16, RealboxBrowserProxy, RealboxElement, RealboxIconElement, RealboxMatchElement} from 'chrome://new-tab-page/new_tab_page.js'; +import {AutocompleteMatch} from 'chrome://new-tab-page/realbox.mojom-webui.js'; import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js'; import {getDeepActiveElement} from 'chrome://resources/js/util.m.js'; -import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; +import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://webui-test/chai_assert.js'; import {eventToPromise} from 'chrome://webui-test/test_util.js'; import {assertStyle, createTheme} from '../test_support.js'; -/** - * @enum {string} - * @const - */ -const CLASSES = { - SELECTED: 'selected', -}; +import {TestRealboxBrowserProxy} from './test_realbox_browser_proxy.js'; -/** - * Helps track realbox browser call arguments. A mocked page handler remote - * resolves the browser call promises with the arguments as an array making the - * tests prone to change if the arguments change. This class extends the page - * handler remote, resolving the browser call promises with named arguments. - * @implements {PageHandlerRemote} - * @extends {TestBrowserProxy} - */ -class TestRealboxBrowserProxy extends TestBrowserProxy { - constructor() { - super([ - 'deleteAutocompleteMatch', - 'executeAction', - 'logCharTypedToRepaintLatency', - 'openAutocompleteMatch', - 'queryAutocomplete', - 'stopAutocomplete', - 'toggleSuggestionGroupIdVisibility', - ]); - } - - /** @override */ - deleteAutocompleteMatch(line) { - this.methodCalled('deleteAutocompleteMatch', {line}); - } - - /** @override */ - executeAction( - line, matchSelectionTimestamp, mouseButton, altKey, ctrlKey, metaKey, - shiftKey) { - this.methodCalled('executeAction', { - line, - matchSelectionTimestamp, - mouseButton, - altKey, - ctrlKey, - metaKey, - shiftKey - }); - } - - /** @override */ - logCharTypedToRepaintLatency(timeDelta) { - this.methodCalled('logCharTypedToRepaintLatency', {timeDelta}); - } - - /** @override */ - openAutocompleteMatch( - line, url, areMatchesShowing, timeElapsedSinceLastFocus, mouseButton, - altKey, ctrlKey, metaKey, shiftKey) { - this.methodCalled('openAutocompleteMatch', { - line, - url, - areMatchesShowing, - timeElapsedSinceLastFocus, - mouseButton, - altKey, - ctrlKey, - metaKey, - shiftKey - }); - } - - /** @override */ - queryAutocomplete(input, preventInlineAutocomplete) { - this.methodCalled('queryAutocomplete', {input, preventInlineAutocomplete}); - } - - /** @override */ - stopAutocomplete(clearResult) { - this.methodCalled('stopAutocomplete', {clearResult}); - } - - /** @override */ - toggleSuggestionGroupIdVisibility(suggestionGroupId) { - this.methodCalled('toggleSuggestionGroupIdVisibility', {suggestionGroupId}); - } +enum Classes { + SELECTED = 'selected', } -/** - * Creates a mock test proxy. - * @return {TestBrowserProxy} - */ -export function createTestProxy() { - const callbackRouter = new PageCallbackRouter(); - return { - callbackRouter, - callbackRouterRemote: callbackRouter.$.bindNewPipeAndPassRemote(), - handler: new TestRealboxBrowserProxy(), - }; -} - -/** - * @param {string} name - * @param {!ClipboardEvent} - */ -function createClipboardEvent(name) { +function createClipboardEvent(name: string): ClipboardEvent { return new ClipboardEvent( name, {cancelable: true, clipboardData: new DataTransfer()}); } -/** - * @param {!Object=} modifiers Things to override about the returned result. - * @return {!search.mojom.AutocompleteMatch} - */ -function createAutocompleteMatch() { +function createAutocompleteMatch(): AutocompleteMatch { return { a11yLabel: mojoString16(''), allowedToBeDefaultMatch: false, @@ -146,14 +45,15 @@ imageUrl: '', removeButtonA11yLabel: mojoString16(''), type: '', + action: undefined, + answer: undefined, + isRichSuggestion: false, + tailSuggestCommonPrefix: undefined, }; } -/** - * @param {!Object=} modifiers Things to override about the returned result. - * @return {!search.mojom.AutocompleteMatch} - */ -function createUrlMatch(modifiers = {}) { +function createUrlMatch(modifiers: Partial<AutocompleteMatch> = {}): + AutocompleteMatch { return Object.assign( createAutocompleteMatch(), { swapContentsAndDescription: true, @@ -166,11 +66,8 @@ modifiers); } -/** - * @param {!Object=} modifiers Things to override about the returned result. - * @return {!search.mojom.AutocompleteMatch} - */ -function createSearchMatch(modifiers = {}) { +function createSearchMatch(modifiers: Partial<AutocompleteMatch> = {}): + AutocompleteMatch { return Object.assign( createAutocompleteMatch(), { isSearchType: true, @@ -185,11 +82,8 @@ modifiers); } -/** - * @param {!Object=} modifiers Things to override about the returned result. - * @return {!search.mojom.AutocompleteMatch} - */ -function createCalculatorMatch(modifiers = {}) { +function createCalculatorMatch(modifiers: Partial<AutocompleteMatch>): + AutocompleteMatch { return Object.assign( createAutocompleteMatch(), { isSearchType: true, @@ -205,12 +99,8 @@ modifiers); } -/** - * Verifies the autocomplete match is showing. - * @param {!search.mojom.AutocompleteMatch} match - * @param {!Element} matchEl - */ -function verifyMatch(match, matchEl) { +/** Verifies the autocomplete match is showing. */ +function verifyMatch(match: AutocompleteMatch, matchEl: RealboxMatchElement) { assertEquals('option', matchEl.getAttribute('role')); const matchContents = decodeString16(match.answer ? match.answer.firstLine : match.contents); @@ -218,9 +108,9 @@ match.answer ? match.answer.secondLine : match.description); const separatorText = matchDescription ? loadTimeData.getString('realboxSeparator') : ''; - const contents = matchEl.$['contents'].textContent.trim(); - const separator = matchEl.$['separator'].textContent.trim(); - const description = matchEl.$['description'].textContent.trim(); + const contents = matchEl.$['contents'].textContent!.trim(); + const separator = matchEl.$['separator'].textContent!.trim(); + const description = matchEl.$['description'].textContent!.trim(); const text = (contents + ' ' + separator + ' ' + description).trim(); assertEquals( match.swapContentsAndDescription ? @@ -230,14 +120,9 @@ } suite('NewTabPageRealboxTest', () => { - /** @type {!RealboxElement} */ - let realbox; + let realbox: RealboxElement; - /** - * @implements {RealboxBrowserProxy} - * @extends {TestBrowserProxy} - */ - let testProxy; + let testProxy: TestRealboxBrowserProxy; suiteSetup(() => { loadTimeData.overrideValues({ @@ -247,39 +132,32 @@ }); setup(async () => { - PolymerTest.clearBody(); + document.body.innerHTML = ''; - testProxy = createTestProxy(); + testProxy = new TestRealboxBrowserProxy(); RealboxBrowserProxy.setInstance(testProxy); realbox = document.createElement('ntp-realbox'); document.body.appendChild(realbox); }); - /** - * @param {!Element} iconElement <ntp-realbox-icon> instance - * @param {string} url - */ - function assertIconBackgroundImageUrl(iconElement, url) { + function assertIconBackgroundImageUrl( + iconElement: RealboxIconElement, url: string) { assertStyle( iconElement.$.icon, 'background-image', `url("chrome://new-tab-page/${url}")`); assertStyle(iconElement.$.icon, '-webkit-mask-image', 'none'); } - /** - * @param {!Element} iconElement <ntp-realbox-icon> instance - * @param {string} url - */ - function assertIconMaskImageUrl(iconElement, url) { + function assertIconMaskImageUrl( + iconElement: RealboxIconElement, url: string) { assertStyle( iconElement.$.icon, '-webkit-mask-image', `url("chrome://new-tab-page/${url}")`); assertStyle(iconElement.$.icon, 'background-image', 'none'); } - /** @return {boolean} */ - function areMatchesShowing() { + function areMatchesShowing(): boolean { return window.getComputedStyle(realbox.$.matches).display !== 'none'; } @@ -344,7 +222,7 @@ loadTimeData.overrideValues({ realboxDefaultIcon: 'search.svg', }); - PolymerTest.clearBody(); + document.body.innerHTML = ''; realbox = document.createElement('ntp-realbox'); document.body.appendChild(realbox); @@ -357,7 +235,7 @@ loadTimeData.overrideValues({ realboxDefaultIcon: 'realbox/icons/google_g.svg', }); - PolymerTest.clearBody(); + document.body.innerHTML = ''; realbox = document.createElement('ntp-realbox'); document.body.appendChild(realbox); @@ -603,17 +481,17 @@ assertTrue(areMatchesShowing()); assertEquals('listbox', realbox.$.matches.getAttribute('role')); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); - verifyMatch(matches[0], matchEls[0]); - verifyMatch(matches[1], matchEls[1]); + verifyMatch(matches[0]!, matchEls[0]!); + verifyMatch(matches[1]!, matchEls[1]!); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); assertEquals(' hello world', realbox.$.input.value); - let start = realbox.$.input.selectionStart; - let end = realbox.$.input.selectionEnd; + let start = realbox.$.input.selectionStart!; + let end = realbox.$.input.selectionEnd!; assertEquals('', realbox.$.input.value.substring(start, end)); }); @@ -642,27 +520,27 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(1, matchEls.length); - verifyMatch(matches[0], matchEls[0]); + verifyMatch(matches[0]!, matchEls[0]!); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); assertEquals('hello world', realbox.$.input.value); - let start = realbox.$.input.selectionStart; - let end = realbox.$.input.selectionEnd; + let start = realbox.$.input.selectionStart!; + let end = realbox.$.input.selectionEnd!; assertEquals('world', realbox.$.input.value.substring(start, end)); // Define a new |value| property on the input to see whether it gets set. let inputValueChanged = false; const originalValueProperty = - Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value'); + Object.getOwnPropertyDescriptor(HTMLInputElement.prototype, 'value')!; Object.defineProperty(realbox.$.input, 'value', { get: originalValueProperty.get, set: (value) => { inputValueChanged = true; - originalValueProperty.set.call(realbox.$.input, value); + originalValueProperty.set!.call(realbox.$.input, value); } }); @@ -680,8 +558,8 @@ assertFalse(inputValueChanged); assertEquals('hello world', realbox.$.input.value); - start = realbox.$.input.selectionStart; - end = realbox.$.input.selectionEnd; + start = realbox.$.input.selectionStart!; + end = realbox.$.input.selectionEnd!; assertEquals('orld', realbox.$.input.value.substring(start, end)); await testProxy.handler.whenCalled('queryAutocomplete').then((args) => { @@ -709,8 +587,8 @@ await testProxy.callbackRouterRemote.$.flushForTesting(); assertEquals('hello', realbox.$.input.value); - const start = realbox.$.input.selectionStart; - const end = realbox.$.input.selectionEnd; + const start = realbox.$.input.selectionStart!; + const end = realbox.$.input.selectionEnd!; assertEquals('hell', realbox.$.input.value.substring(start, end)); }); @@ -728,7 +606,7 @@ assertFalse(areMatchesShowing()); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(0, matchEls.length); }); @@ -746,7 +624,7 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); realbox.$.input.value += 'll'; @@ -761,7 +639,7 @@ assertFalse(areMatchesShowing()); matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(0, matchEls.length); realbox.$.input.value += 'o'; @@ -776,7 +654,7 @@ assertTrue(areMatchesShowing()); matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); }); @@ -812,8 +690,8 @@ await testProxy.callbackRouterRemote.$.flushForTesting(); assertEquals('hello world', realbox.$.input.value); - let start = realbox.$.input.selectionStart; - let end = realbox.$.input.selectionEnd; + let start = realbox.$.input.selectionStart!; + let end = realbox.$.input.selectionEnd!; assertEquals('world', realbox.$.input.value.substring(start, end)); // Select the entire input. @@ -844,8 +722,8 @@ await testProxy.callbackRouterRemote.$.flushForTesting(); assertEquals('helloworld.com', realbox.$.input.value); - let start = realbox.$.input.selectionStart; - let end = realbox.$.input.selectionEnd; + let start = realbox.$.input.selectionStart!; + let end = realbox.$.input.selectionEnd!; assertEquals('world.com', realbox.$.input.value.substring(start, end)); const copyEvent = createClipboardEvent('copy'); @@ -863,13 +741,13 @@ assertTrue(copyEvent.defaultPrevented); assertEquals( 'https://helloworld.com/', - copyEvent.clipboardData.getData('text/plain')); + copyEvent.clipboardData!.getData('text/plain')); realbox.$.input.dispatchEvent(cutEvent); assertTrue(cutEvent.defaultPrevented); assertEquals( 'https://helloworld.com/', - cutEvent.clipboardData.getData('text/plain')); + cutEvent.clipboardData!.getData('text/plain')); }); //============================================================================ @@ -898,11 +776,11 @@ assertTrue(areMatchesShowing()); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); const shiftEnter = new KeyboardEvent('keydown', { bubbles: true, @@ -917,7 +795,7 @@ // Navigates to the first match. await testProxy.handler.whenCalled('openAutocompleteMatch').then((args) => { assertEquals(0, args.line); - assertEquals(matches[0].destinationUrl.url, args.url.url); + assertEquals(matches[0]!.destinationUrl.url, args.url.url); assertTrue(args.areMatchesShowing); assertTrue(args.shiftKey); assertTrue(args.timeElapsedSinceLastFocus.microseconds > 0); @@ -945,25 +823,25 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // Select the first match. - matchEls[0].dispatchEvent(new Event('focusin', { + matchEls[0]!.dispatchEvent(new Event('focusin', { bubbles: true, cancelable: true, composed: true, // So it propagates across shadow DOM boundary. })); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); // Input is updated. assertEquals('hello world', realbox.$.input.value); // Icon is updated. assertIconMaskImageUrl(realbox.$.icon, 'clock.svg'); // Hide the matches by focusing out. - matchEls[0].dispatchEvent(new Event('focusout', { + matchEls[0]!.dispatchEvent(new FocusEvent('focusout', { bubbles: true, cancelable: true, composed: true, // So it propagates across shadow DOM boundary. @@ -976,9 +854,9 @@ realbox.$.matches.$.groups.render(); // First match is still selected. matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); // Input is not cleared. assertEquals('hello world', realbox.$.input.value); // Icon is not cleared. @@ -998,7 +876,7 @@ await testProxy.handler.whenCalled('openAutocompleteMatch') .then((args) => { assertEquals(0, args.line); - assertEquals(matches[0].destinationUrl.url, args.url.url); + assertEquals(matches[0]!.destinationUrl.url, args.url.url); assertFalse(args.areMatchesShowing); assertTrue(args.shiftKey); assertTrue(args.timeElapsedSinceLastFocus.microseconds > 0); @@ -1024,11 +902,11 @@ assertTrue(areMatchesShowing()); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // First match is not selected. - assertFalse(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertFalse(matchEls[0]!.classList.contains(Classes.SELECTED)); const shiftEnter = new KeyboardEvent('keydown', { bubbles: true, @@ -1061,25 +939,25 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // Select the first match. - matchEls[0].dispatchEvent(new Event('focusin', { + matchEls[0]!.dispatchEvent(new Event('focusin', { bubbles: true, cancelable: true, composed: true, // So it propagates across shadow DOM boundary. })); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); // Input is updated. assertEquals('hello world', realbox.$.input.value); // Icon is updated. assertIconMaskImageUrl(realbox.$.icon, 'clock.svg'); // Hide the matches by focusing out. - matchEls[0].dispatchEvent(new Event('focusout', { + matchEls[0]!.dispatchEvent(new FocusEvent('focusout', { bubbles: true, cancelable: true, composed: true, // So it propagates across shadow DOM boundary. @@ -1092,7 +970,7 @@ realbox.$.matches.$.groups.render(); // Matches are cleared. matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(0, matchEls.length); // Input is cleared (zero-prefix case). assertEquals('', realbox.$.input.value); @@ -1136,11 +1014,11 @@ assertTrue(areMatchesShowing()); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); // User types some more and presses Enter before the results update. realbox.$.input.value = 'hello world'; @@ -1168,12 +1046,12 @@ await testProxy.callbackRouterRemote.$.flushForTesting(); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); // Navigates to the first match immediately without further user action. await testProxy.handler.whenCalled('openAutocompleteMatch').then((args) => { assertEquals(0, args.line); - assertEquals(matches[0].destinationUrl.url, args.url.url); + assertEquals(matches[0]!.destinationUrl.url, args.url.url); assertTrue(args.areMatchesShowing); assertTrue(args.shiftKey); assertTrue(args.timeElapsedSinceLastFocus.microseconds > 0); @@ -1203,11 +1081,11 @@ assertTrue(areMatchesShowing()); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); const shiftEnter = new KeyboardEvent('keydown', { bubbles: true, @@ -1216,13 +1094,13 @@ key: 'Enter', shiftKey: true, }); - matchEls[0].dispatchEvent(shiftEnter); + matchEls[0]!.dispatchEvent(shiftEnter); assertTrue(shiftEnter.defaultPrevented); // Navigates to the first match is selected. await testProxy.handler.whenCalled('openAutocompleteMatch').then((args) => { assertEquals(0, args.line); - assertEquals(matches[0].destinationUrl.url, args.url.url); + assertEquals(matches[0]!.destinationUrl.url, args.url.url); assertTrue(args.areMatchesShowing); assertTrue(args.shiftKey); assertTrue(args.timeElapsedSinceLastFocus.microseconds > 0); @@ -1247,7 +1125,7 @@ assertTrue(areMatchesShowing()); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // Right clicks are ignored. @@ -1257,7 +1135,7 @@ cancelable: true, composed: true, // So it propagates across shadow DOM boundary. }); - matchEls[0].dispatchEvent(rightClick); + matchEls[0]!.dispatchEvent(rightClick); assertFalse(rightClick.defaultPrevented); assertEquals(0, testProxy.handler.getCallCount('openAutocompleteMatch')); @@ -1268,12 +1146,12 @@ cancelable: true, composed: true, // So it propagates across shadow DOM boundary. }); - matchEls[0].dispatchEvent(middleClick); + matchEls[0]!.dispatchEvent(middleClick); assertTrue(middleClick.defaultPrevented); await testProxy.handler.whenCalled('openAutocompleteMatch').then((args) => { assertEquals(0, args.line); - assertEquals(matches[0].destinationUrl.url, args.url.url); + assertEquals(matches[0]!.destinationUrl.url, args.url.url); assertTrue(args.areMatchesShowing); assertEquals(1, args.mouseButton); assertTrue(args.timeElapsedSinceLastFocus.microseconds > 0); @@ -1289,12 +1167,12 @@ cancelable: true, composed: true, // So it propagates across shadow DOM boundary. }); - matchEls[0].dispatchEvent(leftClick); + matchEls[0]!.dispatchEvent(leftClick); assertTrue(leftClick.defaultPrevented); await testProxy.handler.whenCalled('openAutocompleteMatch').then((args) => { assertEquals(0, args.line); - assertEquals(matches[0].destinationUrl.url, args.url.url); + assertEquals(matches[0]!.destinationUrl.url, args.url.url); assertTrue(args.areMatchesShowing); assertEquals(0, args.mouseButton); assertTrue(args.timeElapsedSinceLastFocus.microseconds > 0); @@ -1321,12 +1199,13 @@ assertTrue(areMatchesShowing()); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); - assertEquals(window.getComputedStyle(matchEls[0].$.remove).display, 'none'); + assertEquals( + window.getComputedStyle(matchEls[0]!.$.remove).display, 'none'); assertNotEquals( - window.getComputedStyle(matchEls[1].$.remove).display, 'none'); + window.getComputedStyle(matchEls[1]!.$.remove).display, 'none'); }); test('Can remove match using the remove button', async () => { @@ -1344,7 +1223,7 @@ assertTrue(areMatchesShowing()); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // Select the second match. @@ -1356,7 +1235,7 @@ }); realbox.$.input.dispatchEvent(arrowUpEvent); assertTrue(arrowUpEvent.defaultPrevented); - assertTrue(matchEls[1].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[1]!.classList.contains(Classes.SELECTED)); // By pressing 'Enter' on the button. const enter = new KeyboardEvent('keydown', { @@ -1365,7 +1244,7 @@ composed: true, // So it propagates across shadow DOM boundary. key: 'Enter', }); - matchEls[1].$.remove.dispatchEvent(enter); + matchEls[1]!.$.remove.dispatchEvent(enter); assertTrue(enter.defaultPrevented); await testProxy.handler.whenCalled('deleteAutocompleteMatch') .then((args) => { @@ -1378,7 +1257,7 @@ testProxy.handler.reset(); // By clicking the button. - matchEls[1].$.remove.click(); + matchEls[1]!.$.remove.click(); await testProxy.handler.whenCalled('deleteAutocompleteMatch') .then((args) => { assertEquals(1, args.line); @@ -1407,10 +1286,10 @@ assertTrue(areMatchesShowing()); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); // First match does not support deletion. const deleteEvent = new KeyboardEvent('keydown', { @@ -1433,7 +1312,7 @@ assertTrue(arrowDownEvent.defaultPrevented); // Second match is selected. - assertTrue(matchEls[1].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[1]!.classList.contains(Classes.SELECTED)); // Unmodified 'Delete' key does not delete matches. realbox.$.input.dispatchEvent(deleteEvent); @@ -1471,7 +1350,7 @@ assertTrue(areMatchesShowing()); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // By pressing 'Enter' on the button. @@ -1481,7 +1360,7 @@ composed: true, // So it propagates across shadow DOM boundary. key: 'Enter', }); - matchEls[1].$.remove.dispatchEvent(enter); + matchEls[1]!.$.remove.dispatchEvent(enter); assertTrue(enter.defaultPrevented); await testProxy.handler.whenCalled('deleteAutocompleteMatch') .then((args) => { @@ -1492,7 +1371,7 @@ testProxy.handler.reset(); // By clicking the button. - matchEls[1].$.remove.click(); + matchEls[1]!.$.remove.click(); await testProxy.handler.whenCalled('deleteAutocompleteMatch') .then((args) => { assertEquals(1, args.line); @@ -1518,14 +1397,14 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(1, matchEls.length); // First match is not selected. - assertFalse(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertFalse(matchEls[0]!.classList.contains(Classes.SELECTED)); // Remove the first match. - matchEls[0].$.remove.click(); + matchEls[0]!.$.remove.click(); await testProxy.handler.whenCalled('deleteAutocompleteMatch') .then((args) => { assertEquals(0, args.line); @@ -1544,11 +1423,11 @@ assertTrue(areMatchesShowing()); matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(1, matchEls.length); // First match is not selected. - assertFalse(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertFalse(matchEls[0]!.classList.contains(Classes.SELECTED)); let arrowDownEvent = new KeyboardEvent('keydown', { bubbles: true, @@ -1560,7 +1439,7 @@ assertTrue(arrowDownEvent.defaultPrevented); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); assertEquals('https://helloworld.com', realbox.$.input.value); // Remove the first match. @@ -1589,11 +1468,11 @@ assertTrue(areMatchesShowing()); matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(1, matchEls.length); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); assertEquals('hello world', realbox.$.input.value); }); @@ -1615,19 +1494,19 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // Select the second match. - matchEls[1].focus(); - matchEls[1].dispatchEvent(new Event('focusin', { + matchEls[1]!.focus(); + matchEls[1]!.dispatchEvent(new Event('focusin', { bubbles: true, cancelable: true, composed: true, // So it propagates across shadow DOM boundary. })); - assertTrue(matchEls[1].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[1]!.classList.contains(Classes.SELECTED)); assertEquals('https://helloworld.com', realbox.$.input.value); - assertEquals(matchEls[1], realbox.$.matches.shadowRoot.activeElement); + assertEquals(matchEls[1], realbox.$.matches.shadowRoot!.activeElement); let escapeEvent = new KeyboardEvent('keydown', { bubbles: true, @@ -1639,9 +1518,9 @@ assertTrue(escapeEvent.defaultPrevented); // First match gets selected and also gets the focus. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); assertEquals('hello world', realbox.$.input.value); - assertEquals(matchEls[0], realbox.$.matches.shadowRoot.activeElement); + assertEquals(matchEls[0], realbox.$.matches.shadowRoot!.activeElement); escapeEvent = new KeyboardEvent('keydown', { bubbles: true, @@ -1658,7 +1537,7 @@ realbox.$.matches.$.groups.render(); // Matches are cleared. matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(0, matchEls.length); // Input is cleared. assertEquals('', realbox.$.input.value); @@ -1674,7 +1553,7 @@ assertTrue(areMatchesShowing()); matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // Pressing 'Escape' when no matches are selected closes the dropdown. @@ -1693,7 +1572,7 @@ realbox.$.matches.$.groups.render(); // Matches are cleared. matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(0, matchEls.length); }); @@ -1712,7 +1591,7 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); let arrowDownEvent = new KeyboardEvent('keydown', { @@ -1726,9 +1605,9 @@ // First match is selected but does not get focus while focus is in the // input. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); assertEquals('hello world', realbox.$.input.value); - assertEquals(realbox.$.input, realbox.shadowRoot.activeElement); + assertEquals(realbox.$.input, realbox.shadowRoot!.activeElement); // If text is being composed with an IME composition selection is prevented. arrowDownEvent = new KeyboardEvent('keydown', { @@ -1743,9 +1622,9 @@ // First match remains selected and does not get focus while focus is in the // input. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); assertEquals('hello world', realbox.$.input.value); - assertEquals(realbox.$.input, realbox.shadowRoot.activeElement); + assertEquals(realbox.$.input, realbox.shadowRoot!.activeElement); arrowDownEvent = new KeyboardEvent('keydown', { bubbles: true, @@ -1758,22 +1637,22 @@ // Second match gets selected but does not get focus while focus is in the // input. - assertTrue(matchEls[1].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[1]!.classList.contains(Classes.SELECTED)); assertEquals('https://helloworld.com', realbox.$.input.value); - assertEquals(realbox.$.input, realbox.shadowRoot.activeElement); + assertEquals(realbox.$.input, realbox.shadowRoot!.activeElement); // Move the focus to the second match. - matchEls[1].focus(); - matchEls[1].dispatchEvent(new Event('focusin', { + matchEls[1]!.focus(); + matchEls[1]!.dispatchEvent(new Event('focusin', { bubbles: true, cancelable: true, composed: true, // So it propagates across shadow DOM boundary. })); // Second match is selected and has focus. - assertTrue(matchEls[1].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[1]!.classList.contains(Classes.SELECTED)); assertEquals('https://helloworld.com', realbox.$.input.value); - assertEquals(matchEls[1], realbox.$.matches.shadowRoot.activeElement); + assertEquals(matchEls[1], realbox.$.matches.shadowRoot!.activeElement); const arrowUpEvent = new KeyboardEvent('keydown', { bubbles: true, @@ -1781,13 +1660,13 @@ composed: true, // So it propagates across shadow DOM boundary. key: 'ArrowUp', }); - matchEls[1].dispatchEvent(arrowUpEvent); + matchEls[1]!.dispatchEvent(arrowUpEvent); assertTrue(arrowUpEvent.defaultPrevented); // First match gets selected and gets focus while focus is in the matches. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); assertEquals('hello world', realbox.$.input.value); - assertEquals(matchEls[0], realbox.$.matches.shadowRoot.activeElement); + assertEquals(matchEls[0], realbox.$.matches.shadowRoot!.activeElement); }); test('focus indicator', async () => { @@ -1814,9 +1693,9 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); - let focusIndicator = matchEls[0].$['focus-indicator']; + let focusIndicator = matchEls[0]!.$['focus-indicator']; // Select the first match let arrowDownEvent = new KeyboardEvent('keydown', { @@ -1828,24 +1707,24 @@ realbox.$.input.dispatchEvent(arrowDownEvent); assertTrue(arrowDownEvent.defaultPrevented); - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); assertEquals('clear browsing history', realbox.$.input.value); assertEquals(window.getComputedStyle(focusIndicator).display, 'block'); // Give focus to the action button - let action = $$(matchEls[0], '#action'); + const action = $$<HTMLElement>(matchEls[0]!, '#action')!; action.focus(); - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); - assertEquals(action, matchEls[0].shadowRoot.activeElement); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); + assertEquals(action, matchEls[0]!.shadowRoot!.activeElement); assertEquals(window.getComputedStyle(focusIndicator).display, 'none'); // Give focus to remove button - let removeButton = matchEls[0].$.remove; + const removeButton = matchEls[0]!.$.remove; removeButton.focus(); - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); - assertEquals(removeButton, matchEls[0].shadowRoot.activeElement); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); + assertEquals(removeButton, matchEls[0]!.shadowRoot!.activeElement); assertEquals(window.getComputedStyle(focusIndicator).display, 'none'); }); @@ -1899,8 +1778,8 @@ testProxy.handler.reset(); assertEquals('hello', realbox.$.input.value); - let start = realbox.$.input.selectionStart; - let end = realbox.$.input.selectionEnd; + let start = realbox.$.input.selectionStart!; + let end = realbox.$.input.selectionEnd!; assertEquals('ello', realbox.$.input.value.substring(start, end)); // Type the next character of the inline autocompletion. @@ -1940,11 +1819,8 @@ test( 'match and realbox icons are updated when favicon becomes available', async () => { - /** - * @param {!Element} iconElement <ntp-realbox-icon> instance - * @param {string} dataUrl - */ - function assertBackgroundImageDataUrl(iconElement, dataUrl) { + function assertBackgroundImageDataUrl( + iconElement: RealboxIconElement, dataUrl: string) { assertStyle( iconElement.$.icon, 'background-image', `url("${dataUrl}")`); assertStyle(iconElement.$.icon, '-webkit-mask-image', 'none'); @@ -1967,10 +1843,10 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); - assertIconMaskImageUrl(matchEls[0].$.icon, 'clock.svg'); - assertIconMaskImageUrl(matchEls[1].$.icon, 'page.svg'); + assertIconMaskImageUrl(matchEls[0]!.$.icon, 'clock.svg'); + assertIconMaskImageUrl(matchEls[1]!.$.icon, 'page.svg'); assertIconMaskImageUrl(realbox.$.icon, 'search.svg'); // Default icon. // Select the first match. @@ -1984,7 +1860,7 @@ assertTrue(arrowDownEvent.defaultPrevented); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); // Input is updated. assertEquals('hello world', realbox.$.input.value); // Realbox icon is updated. @@ -2001,7 +1877,7 @@ assertTrue(arrowDownEvent.defaultPrevented); // Second match is selected. - assertTrue(matchEls[1].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[1]!.classList.contains(Classes.SELECTED)); // Input is updated. assertEquals('https://helloworld.com', realbox.$.input.value); // Realbox icon is updated. @@ -2011,14 +1887,14 @@ testProxy.callbackRouterRemote.autocompleteMatchImageAvailable( 1, {url: 'http://example.com/'}, faviconData); await testProxy.callbackRouterRemote.$.flushForTesting(); - assertIconMaskImageUrl(matchEls[1].$.icon, 'page.svg'); + assertIconMaskImageUrl(matchEls[1]!.$.icon, 'page.svg'); assertIconMaskImageUrl(realbox.$.icon, 'page.svg'); // Index of the loaded favicon must match index of the match. testProxy.callbackRouterRemote.autocompleteMatchImageAvailable( 0, {url: 'https://helloworld.com/'}, faviconData); await testProxy.callbackRouterRemote.$.flushForTesting(); - assertIconMaskImageUrl(matchEls[1].$.icon, 'page.svg'); + assertIconMaskImageUrl(matchEls[1]!.$.icon, 'page.svg'); assertIconMaskImageUrl(realbox.$.icon, 'page.svg'); // Once the favicon successfully loads it replaces the match icon as @@ -2026,7 +1902,7 @@ testProxy.callbackRouterRemote.autocompleteMatchImageAvailable( 1, {url: 'https://helloworld.com/'}, faviconData); await testProxy.callbackRouterRemote.$.flushForTesting(); - assertBackgroundImageDataUrl(matchEls[1].$.icon, faviconData); + assertBackgroundImageDataUrl(matchEls[1]!.$.icon, faviconData); assertBackgroundImageDataUrl(realbox.$.icon, faviconData); // Select the first match by pressing 'Escape'. @@ -2040,7 +1916,7 @@ assertTrue(escapeEvent.defaultPrevented); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); // Input is updated. assertEquals('hello world', realbox.$.input.value); // Realbox icon is updated. @@ -2099,10 +1975,10 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); - assertIconMaskImageUrl(matchEls[0].$.icon, 'page.svg'); - assertIconMaskImageUrl(matchEls[1].$.icon, 'clock.svg'); + assertIconMaskImageUrl(matchEls[0]!.$.icon, 'page.svg'); + assertIconMaskImageUrl(matchEls[1]!.$.icon, 'clock.svg'); assertIconMaskImageUrl(realbox.$.icon, 'search.svg'); // Default icon. // Select the first match. @@ -2116,7 +1992,7 @@ assertTrue(arrowDownEvent.defaultPrevented); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); // Input is updated. assertEquals('https://helloworld.com', realbox.$.input.value); // Realbox icon is updated. @@ -2133,11 +2009,11 @@ assertTrue(arrowDownEvent.defaultPrevented); // Second match is selected. - assertTrue(matchEls[1].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[1]!.classList.contains(Classes.SELECTED)); // Input is updated. assertEquals('hello world', realbox.$.input.value); // Second match shows a placeholder color until the image loads. - const containerEl = matchEls[1].$.icon.$.container; + const containerEl = matchEls[1]!.$.icon.$.container; assertStyle( containerEl, 'background-color', 'rgba(117, 117, 117, 0.25)'); assertIconMaskImageUrl(realbox.$.icon, 'search.svg'); // Default icon. @@ -2162,7 +2038,8 @@ testProxy.callbackRouterRemote.autocompleteMatchImageAvailable( 1, {url: 'https://gstatic.com/'}, imageData); await testProxy.callbackRouterRemote.$.flushForTesting(); - assertEquals(matchEls[1].$.icon.$.image.getAttribute('src'), imageData); + assertEquals( + matchEls[1]!.$.icon.$.image.getAttribute('src'), imageData); assertStyle(containerEl, 'background-color', 'rgba(0, 0, 0, 0)'); // Realbox icon is not updated as the input does not feature images. assertIconMaskImageUrl(realbox.$.icon, 'search.svg'); // Default icon. @@ -2179,7 +2056,7 @@ assertTrue(escapeEvent.defaultPrevented); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); // Input is updated. assertEquals('https://helloworld.com', realbox.$.input.value); // Realbox icon is updated. @@ -2220,16 +2097,17 @@ // The first match is showing. The second match is initially hidden. assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(1, matchEls.length); // The suggestion group header and the toggle button are visible. const headerEl = - realbox.$.matches.shadowRoot.querySelectorAll('.header')[0]; + realbox.$.matches.shadowRoot!.querySelectorAll<HTMLElement>( + '.header')[0]!; assertTrue(window.getComputedStyle(headerEl).display !== 'none'); - assertEquals('Recommended for you', headerEl.textContent.trim()); + assertEquals('Recommended for you', headerEl.textContent!.trim()); const toggleButtonEl = - realbox.$.matches.shadowRoot.querySelectorAll('cr-icon-button')[0]; + realbox.$.matches.shadowRoot!.querySelectorAll('cr-icon-button')[0]!; assertTrue(window.getComputedStyle(toggleButtonEl).display !== 'none'); // Make the second match visible by pressing 'Space' on the toggle button. @@ -2257,7 +2135,7 @@ // Second match is visible. matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // Hide the second match by clicking the toggle button. @@ -2272,7 +2150,7 @@ // Second match is hidden. matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(1, matchEls.length); testProxy.handler.reset(); @@ -2287,7 +2165,7 @@ 1, testProxy.handler.getCallCount('toggleSuggestionGroupIdVisibility')); // Second match is visible again. matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); }); @@ -2316,24 +2194,25 @@ assertTrue(areMatchesShowing()); const matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(2, matchEls.length); // Select the first match. - matchEls[0].dispatchEvent(new Event('focusin', { + matchEls[0]!.dispatchEvent(new Event('focusin', { bubbles: true, cancelable: true, composed: true, // So it propagates across shadow DOM boundary. })); // First match is selected. - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); // Input is updated. assertEquals('hello world', realbox.$.input.value); // Focus the suggestion group header. const headerEl = - realbox.$.matches.shadowRoot.querySelectorAll('.header')[0]; + realbox.$.matches.shadowRoot!.querySelectorAll<HTMLElement>( + '.header')[0]!; headerEl.dispatchEvent(new Event('focusin', { bubbles: true, cancelable: true, @@ -2341,7 +2220,7 @@ })); // First match is no longer selected. - assertFalse(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertFalse(matchEls[0]!.classList.contains(Classes.SELECTED)); // Input is cleared. assertEquals('', realbox.$.input.value); }); @@ -2365,16 +2244,16 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); assertEquals(1, matchEls.length); - verifyMatch(matches[0], matchEls[0]); - assertIconMaskImageUrl(matchEls[0].$.icon, 'calculator.svg'); + verifyMatch(matches[0]!, matchEls[0]!); + assertIconMaskImageUrl(matchEls[0]!.$.icon, 'calculator.svg'); assertIconMaskImageUrl(realbox.$.icon, 'search.svg'); // Separator is not displayed assertEquals( - window.getComputedStyle(matchEls[0].$.separator).display, 'none'); + window.getComputedStyle(matchEls[0]!.$.separator).display, 'none'); let arrowDownEvent = new KeyboardEvent('keydown', { bubbles: true, @@ -2385,10 +2264,10 @@ realbox.$.input.dispatchEvent(arrowDownEvent); assertTrue(arrowDownEvent.defaultPrevented); - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); assertEquals('5', realbox.$.input.value); - assertIconMaskImageUrl(realbox.$.icon, 'search.svg'); // Default Icon + assertIconMaskImageUrl(realbox.$.icon, 'search.svg'); // Default Icon }); //============================================================================ @@ -2413,12 +2292,12 @@ await testProxy.callbackRouterRemote.$.flushForTesting(); assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); - verifyMatch(matches[0], matchEls[0]); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); + verifyMatch(matches[0]!, matchEls[0]!); // Separator is not displayed assertEquals( - window.getComputedStyle(matchEls[0].$.separator).display, 'none'); + window.getComputedStyle(matchEls[0]!.$.separator).display, 'none'); let arrowDownEvent = new KeyboardEvent('keydown', { bubbles: true, @@ -2429,9 +2308,9 @@ realbox.$.input.dispatchEvent(arrowDownEvent); assertTrue(arrowDownEvent.defaultPrevented); - assertTrue(matchEls[0].classList.contains(CLASSES.SELECTED)); + assertTrue(matchEls[0]!.classList.contains(Classes.SELECTED)); - assertIconMaskImageUrl(realbox.$.icon, 'search.svg'); // Default Icon + assertIconMaskImageUrl(realbox.$.icon, 'search.svg'); // Default Icon }); //============================================================================ @@ -2457,13 +2336,13 @@ await testProxy.callbackRouterRemote.$.flushForTesting(); assertTrue(areMatchesShowing()); - let matchEl = $$(realbox.$.matches, 'ntp-realbox-match'); - verifyMatch(matches[0], matchEl); + let matchEl = $$(realbox.$.matches, 'ntp-realbox-match')!; + verifyMatch(matches[0]!, matchEl); - const pedalEl = $$($$(matchEl, 'ntp-realbox-action'), '.contents'); + const pedalEl = $$($$(matchEl, 'ntp-realbox-action')!, '.contents')!; assertEquals( - pedalEl.querySelector('#action-icon').src, + pedalEl.querySelector<HTMLImageElement>('#action-icon')!.src, 'chrome://theme/current-channel-logo'); // Default Pedal // Icon @@ -2510,14 +2389,14 @@ assertTrue(areMatchesShowing()); let matchEls = - realbox.$.matches.shadowRoot.querySelectorAll('ntp-realbox-match'); - verifyMatch(matches[0], matchEls[0]); - verifyMatch(matches[1], matchEls[1]); + realbox.$.matches.shadowRoot!.querySelectorAll('ntp-realbox-match'); + verifyMatch(matches[0]!, matchEls[0]!); + verifyMatch(matches[1]!, matchEls[1]!); - const pedalEl = $$($$(matchEls[1], 'ntp-realbox-action'), '.contents'); + const pedalEl = $$($$(matchEls[1]!, 'ntp-realbox-action')!, '.contents')!; assertEquals( - pedalEl.querySelector('#action-icon').src, + pedalEl.querySelector<HTMLImageElement>('#action-icon')!.src, 'chrome://theme/current-channel-logo'); // Default Pedal // Icon
diff --git a/chrome/test/data/webui/new_tab_page/realbox/test_realbox_browser_proxy.ts b/chrome/test/data/webui/new_tab_page/realbox/test_realbox_browser_proxy.ts new file mode 100644 index 0000000..05ad90d --- /dev/null +++ b/chrome/test/data/webui/new_tab_page/realbox/test_realbox_browser_proxy.ts
@@ -0,0 +1,100 @@ +// Copyright 2022 The Chromium 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 {PageCallbackRouter, PageHandlerInterface, PageRemote} from 'chrome://new-tab-page/realbox.mojom-webui.js'; +import {String16} from 'chrome://resources/mojo/mojo/public/mojom/base/string16.mojom-webui.js'; +import {TimeDelta, TimeTicks} from 'chrome://resources/mojo/mojo/public/mojom/base/time.mojom-webui.js'; +import {Url} from 'chrome://resources/mojo/url/mojom/url.mojom-webui.js'; +import {TestBrowserProxy} from 'chrome://webui-test/test_browser_proxy.js'; + + +/** + * Helps track realbox browser call arguments. A mocked page handler remote + * resolves the browser call promises with the arguments as an array making the + * tests prone to change if the arguments change. This class extends the page + * handler remote, resolving the browser call promises with named arguments. + */ +class FakePageHandler extends TestBrowserProxy implements PageHandlerInterface { + constructor() { + super([ + 'deleteAutocompleteMatch', + 'executeAction', + 'logCharTypedToRepaintLatency', + 'openAutocompleteMatch', + 'queryAutocomplete', + 'stopAutocomplete', + 'toggleSuggestionGroupIdVisibility', + ]); + } + + setPage(page: PageRemote) { + this.methodCalled('setPage', page); + } + + deleteAutocompleteMatch(line: number) { + this.methodCalled('deleteAutocompleteMatch', {line}); + } + + executeAction( + line: number, matchSelectionTimestamp: TimeTicks, mouseButton: number, + altKey: boolean, ctrlKey: boolean, metaKey: boolean, shiftKey: boolean) { + this.methodCalled('executeAction', { + line, + matchSelectionTimestamp, + mouseButton, + altKey, + ctrlKey, + metaKey, + shiftKey + }); + } + + logCharTypedToRepaintLatency(timeDelta: TimeDelta) { + this.methodCalled('logCharTypedToRepaintLatency', {timeDelta}); + } + + openAutocompleteMatch( + line: number, url: Url, areMatchesShowing: boolean, + timeElapsedSinceLastFocus: TimeDelta, mouseButton: number, + altKey: boolean, ctrlKey: boolean, metaKey: boolean, shiftKey: boolean) { + this.methodCalled('openAutocompleteMatch', { + line, + url, + areMatchesShowing, + timeElapsedSinceLastFocus, + mouseButton, + altKey, + ctrlKey, + metaKey, + shiftKey + }); + } + + queryAutocomplete(input: String16, preventInlineAutocomplete: boolean) { + this.methodCalled('queryAutocomplete', {input, preventInlineAutocomplete}); + } + + stopAutocomplete(clearResult: boolean) { + this.methodCalled('stopAutocomplete', {clearResult}); + } + + toggleSuggestionGroupIdVisibility(suggestionGroupId: number) { + this.methodCalled('toggleSuggestionGroupIdVisibility', {suggestionGroupId}); + } +} + +export class TestRealboxBrowserProxy { + callbackRouter: PageCallbackRouter; + callbackRouterRemote: PageRemote; + handler: FakePageHandler; + + constructor() { + this.callbackRouter = new PageCallbackRouter(); + + this.callbackRouterRemote = + this.callbackRouter.$.bindNewPipeAndPassRemote(); + + this.handler = new FakePageHandler(); + } +}
diff --git a/chrome/test/data/webui/print_preview/BUILD.gn b/chrome/test/data/webui/print_preview/BUILD.gn index 26ff260..180934a 100644 --- a/chrome/test/data/webui/print_preview/BUILD.gn +++ b/chrome/test/data/webui/print_preview/BUILD.gn
@@ -56,11 +56,8 @@ "other_options_settings_test.ts", "pages_per_sheet_settings_test.ts", "pages_settings_test.ts", - - # TODO(rbpotter): Figure out how to enable these while PDF viewer is still - # using JS. - # "pdf_toolbar_manager_test.js", - # "pdf_viewer_test.js", + "pdf_toolbar_manager_test.ts", + "pdf_viewer_test.ts", "pdf_zoom_toolbar_test.ts", "preview_area_test.ts", "scaling_settings_interactive_test.ts", @@ -124,10 +121,15 @@ "chrome://print/pdf/*|" + rebase_path("$root_gen_dir/chrome/browser/resources/pdf/tsc/*", target_gen_dir), + "chrome://print/pdf/pdf_viewer_wrapper.js|" + + rebase_path( + "$root_gen_dir/chrome/browser/resources/pdf/tsc/pdf_viewer_pp.js", + target_gen_dir), "chrome://webui-test/*|" + rebase_path("$root_gen_dir/chrome/test/data/webui/tsc/*", target_gen_dir), ] + definitions = [ "//chrome/browser/resources/pdf/source_capabilities.d.ts" ] in_files = preprocessed_tests + non_preprocessed_tests deps = [ "//chrome/browser/resources/pdf:build_ts",
diff --git a/chrome/test/data/webui/print_preview/pdf_toolbar_manager_test.js b/chrome/test/data/webui/print_preview/pdf_toolbar_manager_test.js deleted file mode 100644 index ccc84b9..0000000 --- a/chrome/test/data/webui/print_preview/pdf_toolbar_manager_test.js +++ /dev/null
@@ -1,267 +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 'chrome://print/pdf/elements/viewer-zoom-toolbar.js'; - -import {ToolbarManager} from 'chrome://print/pdf/toolbar_manager.js'; -import {assert} from 'chrome://resources/js/assert.m.js'; - -import {assertFalse, assertTrue} from '../chai_assert.js'; - -class MockWindow { - /** - * @param {number} width - * @param {number} height - */ - constructor(width, height) { - /** @type {number} */ - this.innerWidth = width; - - /** @type {number} */ - this.innerHeight = height; - - /** @type {number} */ - this.pageXOffset = 0; - - /** @type {number} */ - this.pageYOffset = 0; - - /** @type {?Function} */ - this.scrollCallback = null; - - /** @type {?Function} */ - this.resizeCallback = null; - - /** @type {?Function} */ - this.timerCallback = null; - } - - /** - * @param {string} e The event name - * @param {!Function} f The callback - */ - addEventListener(e, f) { - if (e === 'scroll') { - this.scrollCallback = f; - } - if (e === 'resize') { - this.resizeCallback = f; - } - } - - /** - * @param {number} width - * @param {number} height - */ - setSize(width, height) { - this.innerWidth = width; - this.innerHeight = height; - this.resizeCallback(); - } - - /** - * @param {number} x - * @param {number} y - */ - scrollTo(x, y) { - this.pageXOffset = Math.max(0, x); - this.pageYOffset = Math.max(0, y); - this.scrollCallback(); - } - - /** - * @param {Function} callback - * @return {string} - */ - setTimeout(callback, time) { - this.timerCallback = callback; - return 'timerId'; - } - - /** @param {string} timerId */ - clearTimeout(timerId) { - this.timerCallback = null; - } - - runTimeout() { - if (this.timerCallback) { - this.timerCallback(); - } - } -} - - -// A cut-down version of MockInteractions.move, which is not exposed -// publicly. -function getMouseMoveEvents(fromX, fromY, toX, toY, steps) { - const dx = Math.round((toX - fromX) / steps); - const dy = Math.round((toY - fromY) / steps); - const events = []; - - // Deliberate <= to ensure that an event is run for toX, toY - for (let i = 0; i <= steps; i++) { - const e = new MouseEvent('mousemove', { - clientX: fromX, - clientY: fromY, - movementX: dx, - movementY: dy, - }); - events.push(e); - fromX += dx; - fromY += dy; - } - return events; -} - -function makeTapEvent(x, y) { - const e = new MouseEvent('mousemove', { - clientX: x, - clientY: y, - movementX: 0, - movementY: 0, - sourceCapabilities: new InputDeviceCapabilities({firesTouchEvents: true}) - }); - return e; -} - -window.pdf_toolbar_manager_test = {}; -pdf_toolbar_manager_test.suiteName = 'PdfToolbarManagerTest'; -/** @enum {string} */ -pdf_toolbar_manager_test.TestNames = { - KeyboardNavigation: 'keyboard navigation', - ResetKeyboardNavigation: 'reset keyboard navigation', - TouchInteraction: 'touch interaction', -}; - -suite(pdf_toolbar_manager_test.suiteName, function() { - /** @type {!MockWindow} */ - let mockWindow; - - /** @type {!ViewerZoomToolbarElement} */ - let zoomToolbar; - - /** @type {!ToolbarManager} */ - let toolbarManager; - - /** @type {number} */ - let callCount = 0; - - setup(function() { - document.body.innerHTML = ''; - - mockWindow = new MockWindow(1920, 1080); - zoomToolbar = document.createElement('viewer-zoom-toolbar'); - document.body.appendChild(zoomToolbar); - toolbarManager = new ToolbarManager(mockWindow, zoomToolbar); - toolbarManager.getCurrentTimestamp_ = () => { - callCount = callCount + 1 || 1; - return 1449000000000 + callCount * 50; - }; - }); - - /** - * Test that the toolbar will not be hidden when navigating with the tab key. - */ - test( - assert(pdf_toolbar_manager_test.TestNames.KeyboardNavigation), - function() { - const mouseMove = function(fromX, fromY, toX, toY, steps) { - getMouseMoveEvents(fromX, fromY, toX, toY, steps) - .forEach(function(e) { - document.dispatchEvent(e); - }); - }; - - // Move the mouse and then hit tab -> Toolbar stays open. - mouseMove(200, 200, 800, 800, 5); - toolbarManager.showToolbarForKeyboardNavigation(); - assertTrue(zoomToolbar.isVisible()); - mockWindow.runTimeout(); - assertTrue( - zoomToolbar.isVisible(), - 'toolbar stays open after keyboard navigation'); - - // Use mouse, run timeout -> Toolbar closes. - mouseMove(200, 200, 800, 800, 5); - assertTrue(zoomToolbar.isVisible()); - mockWindow.runTimeout(); - assertFalse(zoomToolbar.isVisible(), 'toolbar closes after mouse move'); - }); - - /** - * Tests that the zoom toolbar becomes visible when it is focused, and is made - * invisible by calling resetKeyboardNavigationAndHideToolbar(). - * Simulates focusing and then un-focusing the zoom toolbar buttons from Print - * Preview. - */ - test( - assert(pdf_toolbar_manager_test.TestNames.ResetKeyboardNavigation), - function() { - // Move the mouse and wait for a timeout to ensure toolbar is invisible. - getMouseMoveEvents(200, 200, 800, 800, 5).forEach(function(e) { - document.dispatchEvent(e); - }); - mockWindow.runTimeout(); - assertFalse(zoomToolbar.isVisible()); - - // Simulate focusing the fit to page button using the tab key. - zoomToolbar.$.fitButton.dispatchEvent( - new CustomEvent('focus', {bubbles: true, composed: true})); - assertTrue(zoomToolbar.isVisible()); - - // Call resetKeyboardNavigationAndHideToolbar(). This happens when focus - // leaves the PDF viewer in Print Preview, and returns to the main Print - // Preview sidebar UI. - toolbarManager.resetKeyboardNavigationAndHideToolbar(); - - assertTrue(zoomToolbar.isVisible()); - - // Simulate re-focusing the zoom toolbar with the tab key. See - // https://crbug.com/982694. - zoomToolbar.$.fitButton.dispatchEvent( - new CustomEvent('keyup', {bubbles: true, composed: true})); - mockWindow.runTimeout(); - assertTrue(zoomToolbar.isVisible()); - - // Simulate focus leaving the PDF viewer again, but this time don't - // refocus the button afterward. - toolbarManager.resetKeyboardNavigationAndHideToolbar(); - assertTrue(zoomToolbar.isVisible()); - mockWindow.runTimeout(); - - // Toolbar should be hidden. - assertFalse(zoomToolbar.isVisible()); - }); - - /* - * Test that the toolbars can be shown or hidden by tapping with a touch - * device. - */ - test(assert(pdf_toolbar_manager_test.TestNames.TouchInteraction), function() { - toolbarManager.resetKeyboardNavigationAndHideToolbar(); - mockWindow.runTimeout(); - assertFalse(zoomToolbar.isVisible()); - - // Tap anywhere on the screen -> Toolbar opens. - document.dispatchEvent(makeTapEvent(500, 500)); - assertTrue(zoomToolbar.isVisible(), 'toolbar opens after tap'); - - // Tap again -> Toolbar closes. - document.dispatchEvent(makeTapEvent(500, 500)); - assertFalse(zoomToolbar.isVisible(), 'toolbar closes after tap'); - - // Open toolbars, wait 2 seconds -> Toolbar closes. - document.dispatchEvent(makeTapEvent(500, 500)); - mockWindow.runTimeout(); - assertFalse(zoomToolbar.isVisible(), 'toolbar closes after wait'); - - // Open toolbar, tap near toolbar -> Toolbar doesn't close. - document.dispatchEvent(makeTapEvent(500, 500)); - document.dispatchEvent(makeTapEvent(100, 1000)); - assertTrue( - zoomToolbar.isVisible(), 'toolbar stays open after tap near toolbar'); - mockWindow.runTimeout(); - assertTrue(zoomToolbar.isVisible(), 'tap near toolbar prevents auto close'); - }); -});
diff --git a/chrome/test/data/webui/print_preview/pdf_toolbar_manager_test.ts b/chrome/test/data/webui/print_preview/pdf_toolbar_manager_test.ts new file mode 100644 index 0000000..8b2b9fd --- /dev/null +++ b/chrome/test/data/webui/print_preview/pdf_toolbar_manager_test.ts
@@ -0,0 +1,243 @@ +// 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 'chrome://print/pdf/elements/viewer-zoom-toolbar.js'; +import {ViewerZoomToolbarElement} from 'chrome://print/pdf/elements/viewer-zoom-toolbar.js'; + +import {ToolbarManager} from 'chrome://print/pdf/toolbar_manager.js'; +import {assert} from 'chrome://resources/js/assert_ts.js'; + +import {assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; + +class MockWindow { + innerWidth: number; + innerHeight: number; + pageXOffset: number = 0; + pageYOffset: number = 0; + resizeCallback: ((param?: any) => void)|null = null; + scrollCallback: ((param?: any) => void)|null = null; + timerCallback: (() => void)|null = null; + + constructor(width: number, height: number) { + this.innerWidth = width; + this.innerHeight = height; + } + + /** + * @param e The event name + * @param f The callback + */ + addEventListener(e: string, f: (param?: any) => void) { + if (e === 'scroll') { + this.scrollCallback = f; + } + if (e === 'resize') { + this.resizeCallback = f; + } + } + + setSize(width: number, height: number) { + this.innerWidth = width; + this.innerHeight = height; + assert(this.resizeCallback); + this.resizeCallback(); + } + + scrollTo(options?: ScrollToOptions|undefined): void; + scrollTo(x: number, y: number): void; + scrollTo(xOrOptions: ScrollToOptions|number|undefined, y?: number) { + this.pageXOffset = Math.max(0, xOrOptions as number); + this.pageYOffset = Math.max(0, y as number); + assert(this.scrollCallback); + this.scrollCallback(); + } + + setTimeout(callback: () => void): number { + this.timerCallback = callback; + return 111; + } + + clearTimeout(_timerId: number|undefined) { + this.timerCallback = null; + } + + runTimeout() { + if (this.timerCallback) { + this.timerCallback(); + } + } +} + + +// A cut-down version of MockInteractions.move, which is not exposed +// publicly. +function getMouseMoveEvents( + fromX: number, fromY: number, toX: number, toY: number, + steps: number): MouseEvent[] { + const dx = Math.round((toX - fromX) / steps); + const dy = Math.round((toY - fromY) / steps); + const events = []; + + // Deliberate <= to ensure that an event is run for toX, toY + for (let i = 0; i <= steps; i++) { + const e = new MouseEvent('mousemove', { + clientX: fromX, + clientY: fromY, + movementX: dx, + movementY: dy, + }); + events.push(e); + fromX += dx; + fromY += dy; + } + return events; +} + +function makeTapEvent(x: number, y: number): MouseEvent { + const e = new MouseEvent('mousemove', { + clientX: x, + clientY: y, + movementX: 0, + movementY: 0, + sourceCapabilities: new InputDeviceCapabilities({firesTouchEvents: true}), + } as MouseEventInit); + return e; +} + +const pdf_toolbar_manager_test = { + suiteName: 'PdfToolbarManagerTest', + TestNames: { + KeyboardNavigation: 'keyboard navigation', + ResetKeyboardNavigation: 'reset keyboard navigation', + TouchInteraction: 'touch interaction', + }, +}; + +Object.assign(window, {pdf_toolbar_manager_test}); + +suite(pdf_toolbar_manager_test.suiteName, function() { + let mockWindow: MockWindow; + + let zoomToolbar: ViewerZoomToolbarElement; + + let toolbarManager: ToolbarManager; + + let callCount: number = 0; + + setup(function() { + document.body.innerHTML = ''; + + mockWindow = new MockWindow(1920, 1080); + zoomToolbar = document.createElement('viewer-zoom-toolbar'); + document.body.appendChild(zoomToolbar); + toolbarManager = + new ToolbarManager(mockWindow as unknown as Window, zoomToolbar); + toolbarManager.getCurrentTimestamp = () => { + callCount = callCount + 1 || 1; + return 1449000000000 + callCount * 50; + }; + }); + + /** + * Test that the toolbar will not be hidden when navigating with the tab key. + */ + test(pdf_toolbar_manager_test.TestNames.KeyboardNavigation, function() { + function mouseMove( + fromX: number, fromY: number, toX: number, toY: number, steps: number) { + getMouseMoveEvents(fromX, fromY, toX, toY, steps) + .forEach(function(e: Event) { + document.dispatchEvent(e); + }); + } + + // Move the mouse and then hit tab -> Toolbar stays open. + mouseMove(200, 200, 800, 800, 5); + toolbarManager.showToolbarForKeyboardNavigation(); + assertTrue(zoomToolbar.isVisible()); + mockWindow.runTimeout(); + assertTrue( + zoomToolbar.isVisible(), + 'toolbar stays open after keyboard navigation'); + + // Use mouse, run timeout -> Toolbar closes. + mouseMove(200, 200, 800, 800, 5); + assertTrue(zoomToolbar.isVisible()); + mockWindow.runTimeout(); + assertFalse(zoomToolbar.isVisible(), 'toolbar closes after mouse move'); + }); + + /** + * Tests that the zoom toolbar becomes visible when it is focused, and is made + * invisible by calling resetKeyboardNavigationAndHideToolbar(). + * Simulates focusing and then un-focusing the zoom toolbar buttons from Print + * Preview. + */ + test(pdf_toolbar_manager_test.TestNames.ResetKeyboardNavigation, function() { + // Move the mouse and wait for a timeout to ensure toolbar is invisible. + getMouseMoveEvents(200, 200, 800, 800, 5).forEach(function(e: Event) { + document.dispatchEvent(e); + }); + mockWindow.runTimeout(); + assertFalse(zoomToolbar.isVisible()); + + // Simulate focusing the fit to page button using the tab key. + zoomToolbar.$.fitButton.dispatchEvent( + new CustomEvent('focus', {bubbles: true, composed: true})); + assertTrue(zoomToolbar.isVisible()); + + // Call resetKeyboardNavigationAndHideToolbar(). This happens when focus + // leaves the PDF viewer in Print Preview, and returns to the main Print + // Preview sidebar UI. + toolbarManager.resetKeyboardNavigationAndHideToolbar(); + + assertTrue(zoomToolbar.isVisible()); + + // Simulate re-focusing the zoom toolbar with the tab key. See + // https://crbug.com/982694. + zoomToolbar.$.fitButton.dispatchEvent( + new CustomEvent('keyup', {bubbles: true, composed: true})); + mockWindow.runTimeout(); + assertTrue(zoomToolbar.isVisible()); + + // Simulate focus leaving the PDF viewer again, but this time don't + // refocus the button afterward. + toolbarManager.resetKeyboardNavigationAndHideToolbar(); + assertTrue(zoomToolbar.isVisible()); + mockWindow.runTimeout(); + + // Toolbar should be hidden. + assertFalse(zoomToolbar.isVisible()); + }); + + /* + * Test that the toolbars can be shown or hidden by tapping with a touch + * device. + */ + test(pdf_toolbar_manager_test.TestNames.TouchInteraction, function() { + toolbarManager.resetKeyboardNavigationAndHideToolbar(); + mockWindow.runTimeout(); + assertFalse(zoomToolbar.isVisible()); + + // Tap anywhere on the screen -> Toolbar opens. + document.dispatchEvent(makeTapEvent(500, 500)); + assertTrue(zoomToolbar.isVisible(), 'toolbar opens after tap'); + + // Tap again -> Toolbar closes. + document.dispatchEvent(makeTapEvent(500, 500)); + assertFalse(zoomToolbar.isVisible(), 'toolbar closes after tap'); + + // Open toolbars, wait 2 seconds -> Toolbar closes. + document.dispatchEvent(makeTapEvent(500, 500)); + mockWindow.runTimeout(); + assertFalse(zoomToolbar.isVisible(), 'toolbar closes after wait'); + + // Open toolbar, tap near toolbar -> Toolbar doesn't close. + document.dispatchEvent(makeTapEvent(500, 500)); + document.dispatchEvent(makeTapEvent(100, 1000)); + assertTrue( + zoomToolbar.isVisible(), 'toolbar stays open after tap near toolbar'); + mockWindow.runTimeout(); + assertTrue(zoomToolbar.isVisible(), 'tap near toolbar prevents auto close'); + }); +});
diff --git a/chrome/test/data/webui/print_preview/pdf_viewer_test.js b/chrome/test/data/webui/print_preview/pdf_viewer_test.js deleted file mode 100644 index cfbed756..0000000 --- a/chrome/test/data/webui/print_preview/pdf_viewer_test.js +++ /dev/null
@@ -1,75 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -/* Suite of tests verifying the PDF viewer as served by Print Preview's data - * source works as expected. */ - -import 'chrome://print/pdf/elements/viewer-page-indicator.js'; - -import {PDFCreateOutOfProcessPlugin} from 'chrome://print/pdf/pdf_scripting_api.js'; -import {assert} from 'chrome://resources/js/assert.m.js'; -import {assertEquals, assertFalse, assertTrue} from '../chai_assert.js'; -import {eventToPromise, waitAfterNextRender} from '../test_util.js'; - -window.pdf_viewer_test = {}; -pdf_viewer_test.suiteName = 'PdfViewerTest'; -/** @enum {string} */ -pdf_viewer_test.TestNames = { - Basic: 'basic', - PageIndicator: 'page indicator', -}; - -suite(pdf_viewer_test.suiteName, function() { - setup(function() { - document.body.innerHTML = ''; - }); - - test(assert(pdf_viewer_test.TestNames.Basic), async () => { - const plugin = PDFCreateOutOfProcessPlugin( - 'chrome-untrusted://print/test.pdf', 'chrome://print/pdf'); - - const loaded = eventToPromise('load', plugin); - document.body.appendChild(plugin); - await loaded; - const viewer = plugin.contentDocument.querySelector('pdf-viewer-pp'); - assertTrue(!!viewer); - assertTrue(plugin.contentDocument.documentElement.hasAttribute( - 'is-print-preview')); - - const verifyElement = id => { - const element = viewer.shadowRoot.querySelector(`viewer-${id}`); - assertTrue(!!element); - assertEquals(id, element.id); - }; - - ['zoom-toolbar', 'page-indicator'].forEach(id => verifyElement(id)); - - // Should also have the sizer and content divs - assertTrue(!!viewer.shadowRoot.querySelector('#sizer')); - assertTrue(!!viewer.shadowRoot.querySelector('#content')); - - // These elements don't exist in Print Preview's viewer. - ['viewer-pdf-toolbar', 'viewer-form-warning'].forEach( - name => assertFalse(!!viewer.shadowRoot.querySelector(name))); - - // The error dialog only appears when it is needed. - assertFalse(!!viewer.shadowRoot.querySelector('viewer-error-dialog')); - viewer.showErrorDialog = true; - await waitAfterNextRender(viewer); - assertTrue(!!viewer.shadowRoot.querySelector('viewer-error-dialog')); - }); - - test(assert(pdf_viewer_test.TestNames.PageIndicator), function() { - const indicator = document.createElement('viewer-page-indicator'); - document.body.appendChild(indicator); - - // Assumes label is index + 1 if no labels are provided - indicator.index = 2; - assertEquals('3', indicator.label); - - // If labels are provided, uses the index to get the label. - indicator.pageLabels = ['1', '3', '5']; - assertEquals('5', indicator.label); - }); -});
diff --git a/chrome/test/data/webui/print_preview/pdf_viewer_test.ts b/chrome/test/data/webui/print_preview/pdf_viewer_test.ts new file mode 100644 index 0000000..6d50c06 --- /dev/null +++ b/chrome/test/data/webui/print_preview/pdf_viewer_test.ts
@@ -0,0 +1,86 @@ +// Copyright 2020 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +/* Suite of tests verifying the PDF viewer as served by Print Preview's data + * source works as expected. */ + +import 'chrome://print/pdf/elements/viewer-page-indicator.js'; +import 'chrome://print/pdf/pdf_viewer_wrapper.js'; + +import {PDFCreateOutOfProcessPlugin} from 'chrome://print/pdf/pdf_scripting_api.js'; +import {PDFViewerPPElement} from 'chrome://print/pdf/pdf_viewer_pp.js'; +import {assertEquals, assertFalse, assertTrue} from 'chrome://webui-test/chai_assert.js'; +import {eventToPromise, waitAfterNextRender} from 'chrome://webui-test/test_util.js'; + +const pdf_viewer_test = { + suiteName: 'PdfViewerTest', + TestNames: { + Basic: 'basic', + PageIndicator: 'page indicator', + }, +}; + +Object.assign(window, {pdf_viewer_test}); + +suite(pdf_viewer_test.suiteName, function() { + setup(function() { + document.body.innerHTML = ''; + }); + + test(pdf_viewer_test.TestNames.Basic, async () => { + const plugin = PDFCreateOutOfProcessPlugin( + 'chrome-untrusted://print/test.pdf', 'chrome://print/pdf'); + + const loaded = eventToPromise('load', plugin); + document.body.appendChild(plugin); + await loaded; + assertTrue(!!plugin.contentDocument); + const viewer: PDFViewerPPElement|null = + plugin.contentDocument.querySelector('pdf-viewer-pp'); + assertTrue(!!viewer); + assertTrue(plugin.contentDocument.documentElement.hasAttribute( + 'is-print-preview')); + + function verifyElement(id: string) { + const element = viewer!.shadowRoot!.querySelector(`viewer-${id}`); + assertTrue(!!element); + if (id === 'zoom-toolbar') { + assertEquals('zoomToolbar', element.id); + } else if (id === 'page-indicator') { + assertEquals('pageIndicator', element.id); + } else { + assertEquals(id, element.id); + } + } + + ['zoom-toolbar', 'page-indicator'].forEach(id => verifyElement(id)); + + // Should also have the sizer and content divs + assertTrue(!!viewer.shadowRoot!.querySelector('#sizer')); + assertTrue(!!viewer.shadowRoot!.querySelector('#content')); + + // These elements don't exist in Print Preview's viewer. + ['viewer-pdf-toolbar', 'viewer-form-warning'].forEach( + name => assertFalse(!!viewer.shadowRoot!.querySelector(name))); + + // The error dialog only appears when it is needed. + assertFalse(!!viewer.shadowRoot!.querySelector('viewer-error-dialog')); + viewer.showErrorDialog = true; + await waitAfterNextRender(viewer); + assertTrue(!!viewer.shadowRoot!.querySelector('viewer-error-dialog')); + }); + + test(pdf_viewer_test.TestNames.PageIndicator, function() { + const indicator = document.createElement('viewer-page-indicator'); + document.body.appendChild(indicator); + + // Assumes label is index + 1 if no labels are provided + indicator.index = 2; + assertEquals('3', indicator.label); + + // If labels are provided, uses the index to get the label. + indicator.pageLabels = [1, 3, 5]; + assertEquals('5', indicator.label); + }); +});
diff --git a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js index 68d6a97..5cdb0037 100644 --- a/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js +++ b/chrome/test/data/webui/print_preview/print_preview_ui_browsertest.js
@@ -139,7 +139,7 @@ var PrintPreviewPdfToolbarManagerTest = class extends PrintPreviewTest { /** @override */ get browsePreload() { - return 'chrome://print/test_loader.html?module=print_preview/pdf_toolbar_manager_test.js'; + return 'chrome://print/test_loader.html?module=print_preview/pdf_toolbar_manager_test.js&host=webui-test'; } /** @override */ @@ -165,7 +165,7 @@ var PrintPreviewPdfViewerTest = class extends PrintPreviewTest { /** @override */ get browsePreload() { - return 'chrome://print/test_loader.html?module=print_preview/pdf_viewer_test.js'; + return 'chrome://print/test_loader.html?module=print_preview/pdf_viewer_test.js&host=webui-test'; } /** @override */
diff --git a/chrome/test/data/webui/settings/chromeos/BUILD.gn b/chrome/test/data/webui/settings/chromeos/BUILD.gn index 0c76d000..434c573 100644 --- a/chrome/test/data/webui/settings/chromeos/BUILD.gn +++ b/chrome/test/data/webui/settings/chromeos/BUILD.gn
@@ -129,6 +129,7 @@ "os_bluetooth_devices_subpage_tests.js", "os_bluetooth_device_detail_subpage_tests.js", "os_bluetooth_change_device_name_dialog_tests.js", + "os_bluetooth_true_wireless_images_tests.js", "os_edit_dictionary_page_test.js", "os_files_page_test.js", "os_languages_page_v2_tests.js",
diff --git a/chrome/test/data/webui/settings/chromeos/app_management/supported_links_item_test.js b/chrome/test/data/webui/settings/chromeos/app_management/supported_links_item_test.js index 4cc18e21..e649ba3a 100644 --- a/chrome/test/data/webui/settings/chromeos/app_management/supported_links_item_test.js +++ b/chrome/test/data/webui/settings/chromeos/app_management/supported_links_item_test.js
@@ -25,11 +25,6 @@ replaceBody(supportedLinksItem); test_util.flushTasks(); - - // TODO(crbug.com/1204324): Remove this line when the feature is launched. - loadTimeData.overrideValues({ - appManagementIntentSettingsEnabled: true, - }); }); test('PWA - preferred -> browser', async function() {
diff --git a/chrome/test/data/webui/settings/chromeos/input_page_test.js b/chrome/test/data/webui/settings/chromeos/input_page_test.js index 31ab03a..227258aa 100644 --- a/chrome/test/data/webui/settings/chromeos/input_page_test.js +++ b/chrome/test/data/webui/settings/chromeos/input_page_test.js
@@ -29,7 +29,6 @@ suiteSetup(() => { CrSettingsPrefs.deferInitialization = true; - loadTimeData.overrideValues({imeOptionsInSettings: true}); }); setup(() => {
diff --git a/chrome/test/data/webui/settings/chromeos/os_bluetooth_device_detail_subpage_tests.js b/chrome/test/data/webui/settings/chromeos/os_bluetooth_device_detail_subpage_tests.js index f6bdf76d..9779b6e 100644 --- a/chrome/test/data/webui/settings/chromeos/os_bluetooth_device_detail_subpage_tests.js +++ b/chrome/test/data/webui/settings/chromeos/os_bluetooth_device_detail_subpage_tests.js
@@ -161,6 +161,76 @@ assertFalse(!!getManagedIcon()); }); + test('True Wireless Images shown when expected', async function() { + init(); + bluetoothConfig.setBluetoothEnabledState(/*enabled=*/ true); + + const getTrueWirelessImages = () => + bluetoothDeviceDetailPage.$$('#trueWirelessImages'); + + const navigateToDeviceDetailPage = () => { + const params = new URLSearchParams(); + params.append('id', '12345/6789&'); + settings.Router.getInstance().navigateTo( + settings.routes.BLUETOOTH_DEVICE_DETAIL, params); + }; + + const device = createDefaultBluetoothDevice( + /*id=*/ '12345/6789&', + /*publicName=*/ 'BeatsX', + /*connectionState=*/ + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kNotConnected, + /*opt_nickname=*/ 'device1', + /*opt_audioCapability=*/ + mojom.AudioOutputCapability.kCapableOfAudioOutput, + /*opt_deviceType=*/ mojom.DeviceType.kMouse, + /*opt_isBlockedByPolicy=*/ true); + const fakeUrl = {url: 'fake_image'}; + // Emulate missing the right bud image. + device.deviceProperties.imageInfo = { + trueWirelessImages: {leftBudImageUrl: fakeUrl, caseImageUrl: fakeUrl} + }; + device.deviceProperties.batteryInfo = { + leftBudInfo: {batteryPercentage: 90} + }; + + bluetoothConfig.appendToPairedDeviceList([device]); + await flushAsync(); + + navigateToDeviceDetailPage(); + + // Don't display component unless all images are present. + await flushAsync(); + assertFalse(!!getTrueWirelessImages()); + + device.deviceProperties.imageInfo.trueWirelessImages.rightBudImageUrl = + fakeUrl; + bluetoothConfig.updatePairedDevice(device); + await flushAsync(); + assertTrue(!!getTrueWirelessImages()); + + // If detailed battery info is not available, only show True Wireless + // component if not connected. + device.deviceProperties.batteryInfo = {}; + device.deviceProperties.connectionState = + mojom.DeviceConnectionState.kNotConnected; + bluetoothConfig.updatePairedDevice(device); + await flushAsync(); + assertTrue(!!getTrueWirelessImages()); + + device.deviceProperties.connectionState = + mojom.DeviceConnectionState.kConnecting; + bluetoothConfig.updatePairedDevice(device); + await flushAsync(); + assertTrue(!!getTrueWirelessImages()); + + device.deviceProperties.connectionState = + mojom.DeviceConnectionState.kConnected; + bluetoothConfig.updatePairedDevice(device); + await flushAsync(); + assertFalse(!!getTrueWirelessImages()); + }); + test('Show change settings row, and navigate to subpages', async function() { init(); bluetoothConfig.setBluetoothEnabledState(/*enabled=*/ true);
diff --git a/chrome/test/data/webui/settings/chromeos/os_bluetooth_true_wireless_images_tests.js b/chrome/test/data/webui/settings/chromeos/os_bluetooth_true_wireless_images_tests.js new file mode 100644 index 0000000..b77bbc9 --- /dev/null +++ b/chrome/test/data/webui/settings/chromeos/os_bluetooth_true_wireless_images_tests.js
@@ -0,0 +1,273 @@ +// Copyright 2022 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// clang-format off +// #import 'chrome://os-settings/chromeos/os_settings.js'; +// #import 'chrome://os-settings/strings.m.js'; + +// #import {BatteryType} from 'chrome://resources/cr_components/chromeos/bluetooth/bluetooth_types.js'; +// #import {flush, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js'; +// #import {createDefaultBluetoothDevice} from 'chrome://test/cr_components/chromeos/bluetooth/fake_bluetooth_config.js'; + +// #import {assertEquals, assertFalse, assertTrue} from '../../../chai_assert.js'; + +// clang-format on + +suite('OsBluetoothTrueWirelessImagesElementTest', function() { + /** @type {SettingsBluetoothTrueWirelessImagesElement} */ + let bluetoothTrueWirelessImages; + + setup(function() { + bluetoothTrueWirelessImages = /** + @type {?SettingsBluetoothTrueWirelessImagesElement} + */ + (document.createElement('os-settings-bluetooth-true-wireless-images')); + const device = createDefaultBluetoothDevice( + /* id= */ '123456789', /* publicName= */ 'BeatsX', + /* connectionState= */ + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kConnected); + bluetoothTrueWirelessImages.device = device.deviceProperties; + document.body.appendChild(bluetoothTrueWirelessImages); + flush(); + }); + + function flushAsync() { + flush(); + return new Promise(resolve => setTimeout(resolve)); + } + + /** + * @param {BatteryType} batteryType + * @param {number} batteryPercentage + */ + async function setBatteryTypePercentage(batteryType, batteryPercentage) { + if (!bluetoothTrueWirelessImages.device.batteryInfo) { + bluetoothTrueWirelessImages.device.batteryInfo = {}; + } + if (batteryType === BatteryType.LEFT_BUD) { + bluetoothTrueWirelessImages.device.batteryInfo.leftBudInfo = { + batteryPercentage: batteryPercentage + }; + } else if (batteryType === BatteryType.CASE) { + bluetoothTrueWirelessImages.device.batteryInfo.caseInfo = { + batteryPercentage: batteryPercentage + }; + } else if (batteryType === BatteryType.RIGHT_BUD) { + bluetoothTrueWirelessImages.device.batteryInfo.rightBudInfo = { + batteryPercentage: batteryPercentage + }; + } + bluetoothTrueWirelessImages.batteryType = batteryType; + bluetoothTrueWirelessImages.device = + /** + * @type {!chromeos.bluetoothConfig.mojom.BluetoothDeviceProperties} + */ + (Object.assign({}, bluetoothTrueWirelessImages.device)); + return flushAsync(); + } + + async function setTrueWirelessImages() { + const fakeUrl = {url: 'fake_image'}; + const trueWireless = { + leftBudImageUrl: fakeUrl, + caseImageUrl: fakeUrl, + rightBudImageUrl: fakeUrl + }; + bluetoothTrueWirelessImages.device.imageInfo = { + trueWirelessImages: trueWireless + }; + + bluetoothTrueWirelessImages.device = + /** + * @type {!chromeos.bluetoothConfig.mojom.BluetoothDeviceProperties} + */ + (Object.assign({}, bluetoothTrueWirelessImages.device)); + return flushAsync(); + } + + test('Connected and all battery info', async function() { + const device = createDefaultBluetoothDevice( + /* id= */ '123456789', /* publicName= */ 'BeatsX', + /* connectionState= */ + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kConnected); + bluetoothTrueWirelessImages.device = device.deviceProperties; + setTrueWirelessImages(); + + const batteryPercentage = 100; + await setBatteryTypePercentage(BatteryType.LEFT_BUD, batteryPercentage); + await setBatteryTypePercentage(BatteryType.CASE, batteryPercentage); + await setBatteryTypePercentage(BatteryType.RIGHT_BUD, batteryPercentage); + + assertTrue(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#leftBudContainer')); + assertTrue(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#caseContainer')); + assertTrue(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#rightBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#notConnectedContainer')); + + assertEquals( + bluetoothTrueWirelessImages.i18n('bluetoothTrueWirelessLeftBudLabel'), + bluetoothTrueWirelessImages.shadowRoot.querySelector('#leftBudLabel') + .innerText.trim()); + assertEquals( + bluetoothTrueWirelessImages.i18n('bluetoothTrueWirelessCaseLabel'), + bluetoothTrueWirelessImages.shadowRoot.querySelector('#caseLabel') + .innerText.trim()); + assertEquals( + bluetoothTrueWirelessImages.i18n('bluetoothTrueWirelessRightBudLabel'), + bluetoothTrueWirelessImages.shadowRoot.querySelector('#rightBudLabel') + .innerText.trim()); + }); + + test('Connected, no battery info', async function() { + const device = createDefaultBluetoothDevice( + /* id= */ '123456789', /* publicName= */ 'BeatsX', + /* connectionState= */ + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kConnected); + bluetoothTrueWirelessImages.device = device.deviceProperties; + setTrueWirelessImages(); + + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#leftBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#caseContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#rightBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#notConnectedContainer')); + }); + + test('Connected and only left bud info', async function() { + const device = createDefaultBluetoothDevice( + /* id= */ '123456789', /* publicName= */ 'BeatsX', + /* connectionState= */ + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kConnected); + bluetoothTrueWirelessImages.device = device.deviceProperties; + setTrueWirelessImages(); + + const batteryPercentage = 100; + await setBatteryTypePercentage(BatteryType.LEFT_BUD, batteryPercentage); + + assertTrue(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#leftBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#caseContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#rightBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#notConnectedContainer')); + }); + + test('Connected and only case info', async function() { + const device = createDefaultBluetoothDevice( + /* id= */ '123456789', /* publicName= */ 'BeatsX', + /* connectionState= */ + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kConnected); + bluetoothTrueWirelessImages.device = device.deviceProperties; + setTrueWirelessImages(); + + const batteryPercentage = 100; + await setBatteryTypePercentage(BatteryType.CASE, batteryPercentage); + + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#leftBudContainer')); + assertTrue(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#caseContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#rightBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#notConnectedContainer')); + }); + + test('Connected and only right bud info', async function() { + const device = createDefaultBluetoothDevice( + /* id= */ '123456789', /* publicName= */ 'BeatsX', + /* connectionState= */ + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kConnected); + bluetoothTrueWirelessImages.device = device.deviceProperties; + setTrueWirelessImages(); + + const batteryPercentage = 100; + await setBatteryTypePercentage(BatteryType.RIGHT_BUD, batteryPercentage); + + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#leftBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#caseContainer')); + assertTrue(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#rightBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#notConnectedContainer')); + }); + + test('Connected and no True Wireless Images', async function() { + const device = createDefaultBluetoothDevice( + /* id= */ '123456789', /* publicName= */ 'BeatsX', + /* connectionState= */ + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kConnected); + bluetoothTrueWirelessImages.device = device.deviceProperties; + + const batteryPercentage = 100; + await setBatteryTypePercentage(BatteryType.LEFT_BUD, batteryPercentage); + await setBatteryTypePercentage(BatteryType.CASE, batteryPercentage); + await setBatteryTypePercentage(BatteryType.RIGHT_BUD, batteryPercentage); + + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#leftBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#caseContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#rightBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#notConnectedContainer')); + }); + + test('Not connected state', async function() { + const device = createDefaultBluetoothDevice( + /* id= */ '123456789', /* publicName= */ 'BeatsX', + /* connectionState= */ + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kNotConnected); + bluetoothTrueWirelessImages.device = device.deviceProperties; + setTrueWirelessImages(); + + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#leftBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#caseContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#rightBudContainer')); + assertTrue(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#notConnectedContainer')); + + assertEquals( + bluetoothTrueWirelessImages.i18n('bluetoothDeviceDetailDisconnected'), + bluetoothTrueWirelessImages.shadowRoot + .querySelector('#notConnectedLabel') + .innerText.trim()); + }); + + test('Not connected and no True Wireless Images', async function() { + const device = createDefaultBluetoothDevice( + /* id= */ '123456789', /* publicName= */ 'BeatsX', + /* connectionState= */ + chromeos.bluetoothConfig.mojom.DeviceConnectionState.kNotConnected); + bluetoothTrueWirelessImages.device = device.deviceProperties; + + const batteryPercentage = 100; + await setBatteryTypePercentage(BatteryType.LEFT_BUD, batteryPercentage); + await setBatteryTypePercentage(BatteryType.CASE, batteryPercentage); + await setBatteryTypePercentage(BatteryType.RIGHT_BUD, batteryPercentage); + + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#leftBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#caseContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#rightBudContainer')); + assertFalse(!!bluetoothTrueWirelessImages.shadowRoot.querySelector( + '#notConnectedContainer')); + }); +});
diff --git a/chrome/test/data/webui/settings/chromeos/os_languages_page_v2_tests.js b/chrome/test/data/webui/settings/chromeos/os_languages_page_v2_tests.js index 82ad9cd..b61c90f 100644 --- a/chrome/test/data/webui/settings/chromeos/os_languages_page_v2_tests.js +++ b/chrome/test/data/webui/settings/chromeos/os_languages_page_v2_tests.js
@@ -40,7 +40,6 @@ suiteSetup(() => { CrSettingsPrefs.deferInitialization = true; - loadTimeData.overrideValues({imeOptionsInSettings: true}); }); setup(async () => {
diff --git a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js index c68ed98..8a31bde 100644 --- a/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js +++ b/chrome/test/data/webui/settings/chromeos/os_settings_v3_browsertest.js
@@ -243,6 +243,29 @@ mocha.run(); }); +// TODO(crbug.com/1237598) Move this test back into the list of tests below once +// Bluetooth revamp is launched. +var OSSettingsOsBluetoothTrueWirelessImagesV3Test = + class extends OSSettingsV3BrowserTest { + /** @override */ + get browsePreload() { + return 'chrome://os-settings/test_loader.html?module=settings/chromeos/os_bluetooth_true_wireless_images_tests.m.js'; + } + + /** @override */ + get featureList() { + return { + enabled: + super.featureList.enabled.concat(['ash::features::kBluetoothRevamp']) + }; + } +}; + +TEST_F('OSSettingsOsBluetoothTrueWirelessImagesV3Test', 'AllJsTests', () => { + mocha.run(); +}); + + var OSSettingsSearchEngineV3Test = class extends OSSettingsV3BrowserTest { /** @override */ get browsePreload() {
diff --git a/chrome/updater/app/server/win/server.cc b/chrome/updater/app/server/win/server.cc index 81c295f..a605f96 100644 --- a/chrome/updater/app/server/win/server.cc +++ b/chrome/updater/app/server/win/server.cc
@@ -52,10 +52,6 @@ namespace updater { namespace { -bool IsCOMService() { - return base::CommandLine::ForCurrentProcess()->HasSwitch(kComServiceSwitch); -} - std::wstring GetCOMGroup(const std::wstring& prefix, UpdaterScope scope) { return base::StrCat({prefix, base::ASCIIToWide(UpdaterScopeToString(scope))}); } @@ -261,7 +257,7 @@ return false; } - if (IsCOMService()) { + if (updater_scope() == UpdaterScope::kSystem) { AddComServiceWorkItems(updater_path, false, list.get()); } else { for (const CLSID& clsid : GetActiveServers(updater_scope())) {
diff --git a/chrome/updater/app/server/win/service_main.cc b/chrome/updater/app/server/win/service_main.cc index 0441df8b..f91648a0db 100644 --- a/chrome/updater/app/server/win/service_main.cc +++ b/chrome/updater/app/server/win/service_main.cc
@@ -14,6 +14,7 @@ #include "base/cxx17_backports.h" #include "base/logging.h" #include "base/no_destructor.h" +#include "base/process/launch.h" #include "base/task/single_thread_task_executor.h" #include "base/win/scoped_com_initializer.h" #include "chrome/updater/app/server/win/com_classes.h" @@ -36,10 +37,27 @@ kServerServiceSwitch) == kServerUpdateServiceInternalSwitchValue; } +HRESULT RunWakeTask() { + base::CommandLine run_updater_wake_command( + base::CommandLine::ForCurrentProcess()->GetProgram()); + run_updater_wake_command.AppendSwitch(kWakeSwitch); + run_updater_wake_command.AppendSwitch(kSystemSwitch); + run_updater_wake_command.AppendSwitch(kEnableLoggingSwitch); + run_updater_wake_command.AppendSwitchASCII(kLoggingModuleSwitch, + kLoggingModuleSwitchValue); + VLOG(2) << "Launching Wake command: " + << run_updater_wake_command.GetCommandLineString(); + + base::LaunchOptions options; + options.start_hidden = true; + const base::Process process = + base::LaunchProcess(run_updater_wake_command, options); + return process.IsValid() ? S_OK : HRESULTFromLastError(); +} + } // namespace -int ServiceMain::RunComService(const base::CommandLine* command_line) { - // Run the COM service. +int ServiceMain::RunWindowsService(const base::CommandLine* command_line) { ServiceMain* service = ServiceMain::GetInstance(); if (!service->InitWithCommandLine(command_line)) return ERROR_BAD_ARGUMENTS; @@ -96,7 +114,7 @@ return service_status_.dwWin32ExitCode; } -void ServiceMain::ServiceMainImpl() { +void ServiceMain::ServiceMainImpl(const base::CommandLine& command_line) { service_status_handle_ = ::RegisterServiceCtrlHandler(GetServiceName(IsInternalService()).c_str(), &ServiceMain::ServiceControlHandler); @@ -108,7 +126,7 @@ // When the Run function returns, the service has stopped. // `hr` can be either a HRESULT or a Windows error code. - const HRESULT hr = Run(); + const HRESULT hr = Run(command_line); if (hr != S_OK) { service_status_.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR; service_status_.dwServiceSpecificExitCode = hr; @@ -118,7 +136,7 @@ } int ServiceMain::RunInteractive() { - return Run(); + return RunCOMServer(); } // static @@ -137,7 +155,7 @@ // static void WINAPI ServiceMain::ServiceMainEntry(DWORD argc, wchar_t* argv[]) { - ServiceMain::GetInstance()->ServiceMainImpl(); + ServiceMain::GetInstance()->ServiceMainImpl(base::CommandLine(argc, argv)); } void ServiceMain::SetServiceStatus(DWORD state) { @@ -145,7 +163,17 @@ ::SetServiceStatus(service_status_handle_, &service_status_); } -HRESULT ServiceMain::Run() { +HRESULT ServiceMain::Run(const base::CommandLine& command_line) { + if (command_line.HasSwitch(kComServiceSwitch)) { + VLOG(2) << "Running COM server within the Windows Service"; + return RunCOMServer(); + } + + VLOG(2) << "Running Wake task from the Windows Service"; + return RunWakeTask(); +} + +HRESULT ServiceMain::RunCOMServer() { base::SingleThreadTaskExecutor service_task_executor( base::MessagePumpType::UI);
diff --git a/chrome/updater/app/server/win/service_main.h b/chrome/updater/app/server/win/service_main.h index d7997d4..0e8e8856 100644 --- a/chrome/updater/app/server/win/service_main.h +++ b/chrome/updater/app/server/win/service_main.h
@@ -24,7 +24,7 @@ // This function is the main entry point for the service. The return value can // be either a Win32 error code or an HRESULT, depending on the API function // that failed. - static int RunComService(const base::CommandLine* command_line); + static int RunWindowsService(const base::CommandLine* command_line); static ServiceMain* GetInstance(); @@ -47,7 +47,7 @@ int RunAsService(); // Runs the service on the service thread. - void ServiceMainImpl(); + void ServiceMainImpl(const base::CommandLine& command_line); // Runs as a local server for testing purposes. RunInteractive returns an // HRESULT, not a Win32 error code. @@ -62,9 +62,12 @@ // Calls ::SetServiceStatus(). void SetServiceStatus(DWORD state); - // Handles object registration, message loop, and unregistration. Returns - // when all registered objects are released. - HRESULT Run(); + // Runs the main logic of the service. + HRESULT Run(const base::CommandLine& command_line); + + // Handles COM object registration, message loop, and unregistration. Returns + // when all COM objects are released. + HRESULT RunCOMServer(); // Calls ::CoInitializeSecurity to allow all users to create COM objects // within the server.
diff --git a/chrome/updater/constants.cc b/chrome/updater/constants.cc index 476dedab..649ad94 100644 --- a/chrome/updater/constants.cc +++ b/chrome/updater/constants.cc
@@ -17,6 +17,7 @@ // Command line arguments. const char kServerSwitch[] = "server"; +const char kWindowsServiceSwitch[] = "windows-service"; const char kComServiceSwitch[] = "com-service"; const char kCrashMeSwitch[] = "crash-me"; const char kCrashHandlerSwitch[] = "crash-handler";
diff --git a/chrome/updater/constants.h b/chrome/updater/constants.h index 563e6a1..39dfbe8 100644 --- a/chrome/updater/constants.h +++ b/chrome/updater/constants.h
@@ -50,10 +50,15 @@ extern const char kServerUpdateServiceInternalSwitchValue[]; extern const char kServerUpdateServiceSwitchValue[]; -// This switch starts the COM service. This switch is invoked by the Service -// Manager when CoCreate is called on one of several CLSIDs that the server -// supports. -// We expect to use the COM service for the following scenarios: +// This switch starts the Windows service. This switch is invoked by the SCM +// either as a part of system startup (`SERVICE_AUTO_START`) or when `CoCreate` +// is called on one of several CLSIDs that the server supports. +extern const char kWindowsServiceSwitch[]; + +// This switch indicates that the Windows service is in the COM server mode. +// This switch is passed to `ServiceMain` by the SCM when CoCreate is called on +// one of several CLSIDs that the server supports. We expect to use the COM +// service for the following scenarios: // * The Server for the UI when installing Machine applications. // * The On-Demand COM Server for Machine applications. // * COM Server for launching processes at System Integrity, i.e., an Elevator.
diff --git a/chrome/updater/updater.cc b/chrome/updater/updater.cc index 5a37fcc..ff64f02 100644 --- a/chrome/updater/updater.cc +++ b/chrome/updater/updater.cc
@@ -164,8 +164,8 @@ return MakeAppUpdate()->Run(); #if BUILDFLAG(IS_WIN) - if (command_line->HasSwitch(kComServiceSwitch)) - return ServiceMain::RunComService(command_line); + if (command_line->HasSwitch(kWindowsServiceSwitch)) + return ServiceMain::RunWindowsService(command_line); if (command_line->HasSwitch(kHealthCheckSwitch)) { return 0; @@ -203,11 +203,21 @@ const char* GetUpdaterCommand(const base::CommandLine* command_line) { // Contains the literals which are associated with specific updater commands. const char* commands[] = { - kComServiceSwitch, kCrashHandlerSwitch, kHealthCheckSwitch, - kInstallSwitch, kRecoverSwitch, kServerSwitch, - kTagSwitch, kTestSwitch, kUninstallIfUnusedSwitch, - kUninstallSelfSwitch, kUninstallSwitch, kUpdateSwitch, - kWakeSwitch, kHealthCheckSwitch, kHandoffSwitch, + kWindowsServiceSwitch, + kCrashHandlerSwitch, + kHealthCheckSwitch, + kInstallSwitch, + kRecoverSwitch, + kServerSwitch, + kTagSwitch, + kTestSwitch, + kUninstallIfUnusedSwitch, + kUninstallSelfSwitch, + kUninstallSwitch, + kUpdateSwitch, + kWakeSwitch, + kHealthCheckSwitch, + kHandoffSwitch, }; const char** it = std::find_if( std::begin(commands), std::end(commands),
diff --git a/chrome/updater/win/setup/setup.cc b/chrome/updater/win/setup/setup.cc index bccc6aa..0b115df 100644 --- a/chrome/updater/win/setup/setup.cc +++ b/chrome/updater/win/setup/setup.cc
@@ -21,6 +21,7 @@ #include "base/strings/strcat.h" #include "base/strings/utf_string_conversions.h" #include "base/version.h" +#include "base/win/scoped_com_initializer.h" #include "base/win/win_util.h" #include "chrome/installer/util/self_cleaning_temp_dir.h" #include "chrome/installer/util/work_item_list.h" @@ -112,6 +113,10 @@ break; } + auto scoped_com_initializer = + std::make_unique<base::win::ScopedCOMInitializer>( + base::win::ScopedCOMInitializer::kMTA); + base::FilePath temp_dir; if (!base::GetTempDir(&temp_dir)) { LOG(ERROR) << "GetTempDir failed.";
diff --git a/chrome/updater/win/setup/setup_util.cc b/chrome/updater/win/setup/setup_util.cc index 07c6321..fd69513 100644 --- a/chrome/updater/win/setup/setup_util.cc +++ b/chrome/updater/win/setup/setup_util.cc
@@ -245,7 +245,7 @@ // This assumes the COM service runs elevated and in the system updater scope. base::CommandLine com_service_command(com_service_path); com_service_command.AppendSwitch(kSystemSwitch); - com_service_command.AppendSwitch(kComServiceSwitch); + com_service_command.AppendSwitch(kWindowsServiceSwitch); com_service_command.AppendSwitchASCII( kServerServiceSwitch, internal_service ? kServerUpdateServiceInternalSwitchValue @@ -254,16 +254,13 @@ com_service_command.AppendSwitchASCII(kLoggingModuleSwitch, kLoggingModuleSwitchValue); - // TODO(crbug.com/1292806) : SERVICE_DEMAND_START will change to - // SERVICE_AUTO_START once the Wake task is plumbed into the service startup. - // TODO(crbug.com/1292806) : the `com_service_cmd_line_args` will change from - // base::CommandLine(base::CommandLine::NO_PROGRAM) to switches that indicate - // a COM activation once the Wake task is plumbed into the service startup. + base::CommandLine com_switch(base::CommandLine::NO_PROGRAM); + com_switch.AppendSwitch(kComServiceSwitch); + list->AddWorkItem(new installer::InstallServiceWorkItem( GetServiceName(internal_service).c_str(), - GetServiceDisplayName(internal_service).c_str(), SERVICE_DEMAND_START, - com_service_command, base::CommandLine(base::CommandLine::NO_PROGRAM), - UPDATER_KEY, + GetServiceDisplayName(internal_service).c_str(), SERVICE_AUTO_START, + com_service_command, com_switch, UPDATER_KEY, internal_service ? GetSideBySideServers(UpdaterScope::kSystem) : GetActiveServers(UpdaterScope::kSystem), {}));
diff --git a/chrome/updater/win/setup/uninstall.cc b/chrome/updater/win/setup/uninstall.cc index 9283c2b..f1e6c3fe 100644 --- a/chrome/updater/win/setup/uninstall.cc +++ b/chrome/updater/win/setup/uninstall.cc
@@ -19,6 +19,7 @@ #include "base/process/launch.h" #include "base/process/process.h" #include "base/strings/stringprintf.h" +#include "base/win/scoped_com_initializer.h" #include "chrome/installer/util/install_service_work_item.h" #include "chrome/installer/util/install_util.h" #include "chrome/installer/util/work_item_list.h" @@ -145,6 +146,10 @@ HKEY key = scope == UpdaterScope::kSystem ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; + auto scoped_com_initializer = + std::make_unique<base::win::ScopedCOMInitializer>( + base::win::ScopedCOMInitializer::kMTA); + updater::UnregisterWakeTask(scope); if (uninstall_all) {
diff --git a/chromecast/renderer/cast_content_renderer_client.cc b/chromecast/renderer/cast_content_renderer_client.cc index 2dce735..791d858 100644 --- a/chromecast/renderer/cast_content_renderer_client.cc +++ b/chromecast/renderer/cast_content_renderer_client.cc
@@ -233,12 +233,13 @@ #endif } -void CastContentRendererClient::AddSupportedKeySystems( - std::vector<std::unique_ptr<::media::KeySystemProperties>>* - key_systems_properties) { - media::AddChromecastKeySystems(key_systems_properties, +void CastContentRendererClient::GetSupportedKeySystems( + ::media::GetSupportedKeySystemsCB cb) { + ::media::KeySystemPropertiesVector key_systems; + media::AddChromecastKeySystems(&key_systems, false /* enable_persistent_license_support */, false /* enable_playready */); + std::move(cb).Run(std::move(key_systems)); } bool CastContentRendererClient::IsSupportedAudioType(
diff --git a/chromecast/renderer/cast_content_renderer_client.h b/chromecast/renderer/cast_content_renderer_client.h index d9ce1403..c823b35 100644 --- a/chromecast/renderer/cast_content_renderer_client.h +++ b/chromecast/renderer/cast_content_renderer_client.h
@@ -64,9 +64,7 @@ void RenderFrameCreated(content::RenderFrame* render_frame) override; void RunScriptsAtDocumentStart(content::RenderFrame* render_frame) override; void RunScriptsAtDocumentEnd(content::RenderFrame* render_frame) override; - void AddSupportedKeySystems( - std::vector<std::unique_ptr<::media::KeySystemProperties>>* - key_systems_properties) override; + void GetSupportedKeySystems(::media::GetSupportedKeySystemsCB cb) override; bool IsSupportedAudioType(const ::media::AudioType& type) override; bool IsSupportedVideoType(const ::media::VideoType& type) override; bool IsSupportedBitstreamAudioCodec(::media::AudioCodec codec) override;
diff --git a/chromeos/network/metrics/connection_info_metrics_logger.cc b/chromeos/network/metrics/connection_info_metrics_logger.cc index 048fabd7..fb24364d 100644 --- a/chromeos/network/metrics/connection_info_metrics_logger.cc +++ b/chromeos/network/metrics/connection_info_metrics_logger.cc
@@ -10,19 +10,19 @@ #include "chromeos/network/network_connection_handler.h" #include "chromeos/network/network_state.h" #include "chromeos/network/network_state_handler.h" +#include "third_party/cros_system_api/dbus/shill/dbus-constants.h" namespace chromeos { ConnectionInfoMetricsLogger::ConnectionInfo::ConnectionInfo( - const NetworkState* network, - bool was_disconnect_requested) - : guid(network->guid()), - shill_error(network->GetError()), - was_disconnect_requested(was_disconnect_requested) { + const NetworkState* network) + : guid(network->guid()), shill_error(network->GetError()) { if (network->IsConnectedState()) status = Status::kConnected; else if (network->IsConnectingState()) status = Status::kConnecting; + else if (network->connection_state() == shill::kStateDisconnect) + status = Status::kDisconnecting; else status = Status::kDisconnected; } @@ -31,9 +31,8 @@ bool ConnectionInfoMetricsLogger::ConnectionInfo::operator==( const ConnectionInfoMetricsLogger::ConnectionInfo& other) const { - return status == other.status && - was_disconnect_requested == other.was_disconnect_requested && - guid == other.guid && shill_error == other.shill_error; + return status == other.status && guid == other.guid && + shill_error == other.shill_error; } ConnectionInfoMetricsLogger::ConnectionInfoMetricsLogger() = default; @@ -88,20 +87,6 @@ UpdateConnectionInfo(network); } -void ConnectionInfoMetricsLogger::DisconnectRequested( - const std::string& service_path) { - if (!network_state_handler_) - return; - - const NetworkState* network = - network_state_handler_->GetNetworkState(service_path); - - if (!network) - return; - - UpdateConnectionInfo(network, /*disconnect_requested=*/true); -} - void ConnectionInfoMetricsLogger::ConnectSucceeded( const std::string& service_path) { const NetworkState* network = @@ -126,13 +111,10 @@ } void ConnectionInfoMetricsLogger::UpdateConnectionInfo( - const NetworkState* network, - bool disconnect_requested) { + const NetworkState* network) { const absl::optional<ConnectionInfo> prev_info = GetCachedInfo(network->guid()); - ConnectionInfo curr_info = - ConnectionInfo(network, - /*was_disconnect_requested=*/disconnect_requested); + const ConnectionInfo& curr_info = ConnectionInfo(network); // No updates if the ConnectionInfo did not change. if (prev_info == curr_info) @@ -144,8 +126,6 @@ if (!prev_info || prev_info->status != curr_info.status) { AttemptLogAllConnectionResult(prev_info, curr_info); AttemptLogConnectionStateResult(prev_info, curr_info); - } else if (prev_info && prev_info->was_disconnect_requested) { - curr_info.was_disconnect_requested = true; } guid_to_connection_info_.insert_or_assign(network->guid(), curr_info); } @@ -159,11 +139,12 @@ return; } - // If the network becomes disconnected from a connected state without a - // user initiated disconnect request. + // If the network becomes disconnected or disconnecting from a connected state + // as a result of a shill error. if (prev_info && prev_info->status == ConnectionInfo::Status::kConnected && - curr_info.status == ConnectionInfo::Status::kDisconnected && - (!prev_info->was_disconnect_requested)) { + (curr_info.status == ConnectionInfo::Status::kDisconnected || + curr_info.status == ConnectionInfo::Status::kDisconnecting) && + NetworkState::ErrorIsValid(curr_info.shill_error)) { NetworkMetricsHelper::LogConnectionStateResult( curr_info.guid, NetworkMetricsHelper::ConnectionState::kDisconnectedWithoutUserAction); @@ -179,9 +160,13 @@ if (curr_info.status == ConnectionInfo::Status::kConnected) NetworkMetricsHelper::LogAllConnectionResult(curr_info.guid); - if (prev_info && !prev_info->was_disconnect_requested && - prev_info->status == ConnectionInfo::Status::kConnecting && - curr_info.status == ConnectionInfo::Status::kDisconnected) { + // If the network goes from connecting or disconnecting state to the + // disconnected state, log the shill error if it's valid. + if (prev_info && + (prev_info->status == ConnectionInfo::Status::kConnecting || + prev_info->status == ConnectionInfo::Status::kDisconnecting) && + curr_info.status == ConnectionInfo::Status::kDisconnected && + NetworkState::ErrorIsValid(curr_info.shill_error)) { NetworkMetricsHelper::LogAllConnectionResult(curr_info.guid, curr_info.shill_error); }
diff --git a/chromeos/network/metrics/connection_info_metrics_logger.h b/chromeos/network/metrics/connection_info_metrics_logger.h index 0470c12..25024ec 100644 --- a/chromeos/network/metrics/connection_info_metrics_logger.h +++ b/chromeos/network/metrics/connection_info_metrics_logger.h
@@ -47,7 +47,7 @@ struct ConnectionInfo { public: enum class Status { - // The network is not connected or being connected to. + // The network is not connected, connecting, or disconnecting. kDisconnected = 0, // The network is being connected to. @@ -55,9 +55,12 @@ // The network is connected. kConnected = 2, + + // The network is disconnecting. + kDisconnecting = 3, }; - ConnectionInfo(const NetworkState* network, bool was_disconnect_requested); + ConnectionInfo(const NetworkState* network); ~ConnectionInfo(); bool operator==(const ConnectionInfo& other) const; @@ -65,7 +68,6 @@ Status status; std::string guid; std::string shill_error; - bool was_disconnect_requested; }; // NetworkStateHandlerObserver:: @@ -73,13 +75,11 @@ void NetworkConnectionStateChanged(const NetworkState* network) override; // NetworkConnectionObserver:: - void DisconnectRequested(const std::string& service_path) override; void ConnectSucceeded(const std::string& service_path) override; void ConnectFailed(const std::string& service_path, const std::string& error_name) override; - void UpdateConnectionInfo(const NetworkState* network, - bool disconnect_requested = false); + void UpdateConnectionInfo(const NetworkState* network); void AttemptLogAllConnectionResult( const absl::optional<ConnectionInfo>& prev_info, const ConnectionInfo& curr_info) const; @@ -88,8 +88,8 @@ const ConnectionInfo& curr_info) const; absl::optional<ConnectionInfo> GetCachedInfo(const std::string& guid) const; - NetworkStateHandler* network_state_handler_; - NetworkConnectionHandler* network_connection_handler_; + NetworkStateHandler* network_state_handler_ = nullptr; + NetworkConnectionHandler* network_connection_handler_ = nullptr; // Stores connection information for all networks. base::flat_map<std::string, ConnectionInfo> guid_to_connection_info_;
diff --git a/chromeos/network/metrics/connection_info_metrics_logger_unittest.cc b/chromeos/network/metrics/connection_info_metrics_logger_unittest.cc index eb15d74c..44b3355 100644 --- a/chromeos/network/metrics/connection_info_metrics_logger_unittest.cc +++ b/chromeos/network/metrics/connection_info_metrics_logger_unittest.cc
@@ -102,9 +102,11 @@ base::RunLoop().RunUntilIdle(); } - void RequestDisconnect(const std::string& service_path) { - chromeos::NetworkHandler::Get() - ->connection_info_metrics_logger_->DisconnectRequested(service_path); + void SetShillError(const std::string& service_path, + const std::string& shill_error) { + shill_service_client_->SetServiceProperty( + service_path, shill::kErrorProperty, base::Value(shill_error)); + base::RunLoop().RunUntilIdle(); } void TriggerUserInitiatedConnectSuccess(const std::string& service_path) { @@ -141,7 +143,8 @@ kCellularConnectionStateHistogram, NetworkMetricsHelper::ConnectionState::kConnected, 1); - // Disconnected Cellular without explicit request from user to disconnect. + // Disconnected Cellular with error. + SetShillError(kCellularServicePath, shill::kErrorConnectFailed); SetShillState(kCellularServicePath, shill::kStateIdle); histogram_tester_->ExpectTotalCount(kCellularConnectionStateHistogram, 2); histogram_tester_->ExpectBucketCount( @@ -157,7 +160,8 @@ kWifiConnectionStateHistogram, NetworkMetricsHelper::ConnectionState::kConnected, 1); - // Disconnected Wifi without explicit request from user to disconnect. + // Disconnecting Wifi because of an error. + SetShillError(kWifiServicePath, shill::kErrorConnectFailed); SetShillState(kWifiServicePath, shill::kStateIdle); histogram_tester_->ExpectTotalCount(kWifiConnectionStateHistogram, 2); histogram_tester_->ExpectBucketCount( @@ -209,14 +213,19 @@ histogram_tester_->ExpectBucketCount(kCellularConnectResultAllHistogram, ShillConnectResult::kSuccess, 2); - // Fail to connect from connecting to disconnected without disconnection - // request. + // Fail to connect from connecting to disconnecting, no valid shill error. SetShillState(kCellularServicePath, shill::kStateAssociation); histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 2); + SetShillState(kCellularServicePath, shill::kStateDisconnect); + histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 2); + + // Fail to connect from disconnecting to disconnected. + SetShillError(kCellularServicePath, shill::kErrorConnectFailed); SetShillState(kCellularServicePath, shill::kStateIdle); histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 3); histogram_tester_->ExpectBucketCount(kCellularConnectResultAllHistogram, - ShillConnectResult::kUnknown, 1); + ShillConnectResult::kErrorConnectFailed, + 1); } TEST_F(ConnectionInfoMetricsLoggerTest, MultipleNetworksStatusRecorded) { @@ -240,6 +249,7 @@ ShillConnectResult::kSuccess, 1); SetShillState(kWifiServicePath, shill::kStateAssociation); + SetShillError(kWifiServicePath, shill::kErrorConnectFailed); SetShillState(kWifiServicePath, shill::kStateIdle); histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 1); histogram_tester_->ExpectTotalCount(kWifiConnectResultAllHistogram, 2); @@ -247,38 +257,4 @@ ShillConnectResult::kSuccess, 1); } -TEST_F(ConnectionInfoMetricsLoggerTest, DisconnectRequested) { - SetUpGenericCellularNetwork(); - - // Disconnect Requested while connected. - SetShillState(kCellularServicePath, shill::kStateOnline); - histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 1); - RequestDisconnect(kCellularServicePath); - histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 1); - SetShillState(kCellularServicePath, shill::kStateReady); - histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 1); - - // Disconnect Requested while disconnected. - SetShillState(kCellularServicePath, shill::kStateIdle); - histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 1); - RequestDisconnect(kCellularServicePath); - SetShillState(kCellularServicePath, shill::kStateDisconnect); - histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 1); - - // Disconnect Requested while connecting. - SetShillState(kCellularServicePath, shill::kStateAssociation); - histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 1); - RequestDisconnect(kCellularServicePath); - SetShillState(kCellularServicePath, shill::kStateConfiguration); - histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 1); - - // Cancel connect attempt while connecting state. - SetShillState(kCellularServicePath, shill::kStateAssociation); - histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 1); - SetShillState(kCellularServicePath, shill::kStateAssociation); - RequestDisconnect(kCellularServicePath); - SetShillState(kCellularServicePath, shill::kStateIdle); - histogram_tester_->ExpectTotalCount(kCellularConnectResultAllHistogram, 1); -} - } // namespace chromeos \ No newline at end of file
diff --git a/chromeos/services/network_config/cros_network_config.cc b/chromeos/services/network_config/cros_network_config.cc index bf56739..239158e 100644 --- a/chromeos/services/network_config/cros_network_config.cc +++ b/chromeos/services/network_config/cros_network_config.cc
@@ -604,9 +604,9 @@ const base::Value* v = dict->FindKey(key); if (v && !v->is_int()) { NET_LOG(ERROR) << "Expected int, found: " << *v; - return false; + return 0; } - return v ? v->GetInt() : false; + return v ? v->GetInt() : 0; } std::vector<int32_t> GetInt32List(const base::Value* dict, const char* key) {
diff --git a/components/autofill_assistant/OWNERS b/components/autofill_assistant/OWNERS index 362142f1..486dae3c 100644 --- a/components/autofill_assistant/OWNERS +++ b/components/autofill_assistant/OWNERS
@@ -1,6 +1,4 @@ # Please keep these in alphabetical order arbesser@google.com hluca@google.com -marianfe@google.com -mcarlen@chromium.org sandromaggi@google.com
diff --git a/components/autofill_assistant/browser/devtools/value_conversions.h b/components/autofill_assistant/browser/devtools/value_conversions.h index 082701e..288c53a 100644 --- a/components/autofill_assistant/browser/devtools/value_conversions.h +++ b/components/autofill_assistant/browser/devtools/value_conversions.h
@@ -56,7 +56,7 @@ template <typename T> std::unique_ptr<base::Value> ToValueImpl(const base::Value& value, T*) { - return value.CreateDeepCopy(); + return std::make_unique<base::Value>(value.Clone()); } template <typename T>
diff --git a/components/bookmarks/browser/titled_url_index.cc b/components/bookmarks/browser/titled_url_index.cc index 40fa198..f8dce88 100644 --- a/components/bookmarks/browser/titled_url_index.cc +++ b/components/bookmarks/browser/titled_url_index.cc
@@ -6,10 +6,15 @@ #include <stdint.h> +#include <algorithm> +#include <unordered_set> +#include <utility> + #include "base/containers/cxx20_erase.h" #include "base/i18n/case_conversion.h" #include "base/i18n/unicodestring.h" #include "base/logging.h" +#include "base/ranges/algorithm.h" #include "base/stl_util.h" #include "base/strings/utf_offset_string_conversions.h" #include "build/build_config.h" @@ -24,6 +29,11 @@ namespace { +// The maximum number of nodes to fetch when looking for nodes that match any +// term (i.e. when invoking `RetrieveNodesMatchingAnyTerms()`). Parameterized +// for testing. +constexpr size_t kMatchingAnyTermsMaxNodes = 3000; + // Returns a normalized version of the UTF16 string |text|. If it fails to // normalize the string, returns |text| itself as a best-effort. std::u16string Normalize(const std::u16string& text) { @@ -77,6 +87,8 @@ bool match_ancestor_titles) { const std::u16string query = Normalize(input_query); std::vector<std::u16string> terms = ExtractQueryWords(query); + if (terms.empty()) + return {}; // When |match_ancestor_titles| is true, |matches| shouldn't exclude nodes // that don't match every query term, as the query terms may match in the @@ -84,8 +96,10 @@ // neither match nor ancestor-match every query term. TitledUrlNodeSet matches = match_ancestor_titles - ? RetrieveNodesMatchingAnyTerms(terms, matching_algorithm) + ? RetrieveNodesMatchingAnyTerms(terms, matching_algorithm, + kMatchingAnyTermsMaxNodes) : RetrieveNodesMatchingAllTerms(terms, matching_algorithm); + if (matches.empty()) return {}; @@ -99,20 +113,8 @@ query_parser::QueryParser::ParseQueryNodes(query, matching_algorithm, &query_nodes); - // The highest typed counts should be at the beginning of the results vector - // so that the best matches will always be included in the results. The loop - // that calculates result relevance in HistoryContentsProvider::ConvertResults - // will run backwards to assure higher relevance will be attributed to the - // best matches. - std::vector<TitledUrlMatch> results; - for (TitledUrlNodes::const_iterator i = sorted_nodes.begin(); - i != sorted_nodes.end() && results.size() < max_count; ++i) { - absl::optional<TitledUrlMatch> match = - MatchTitledUrlNodeWithQuery(*i, query_nodes, match_ancestor_titles); - if (match) - results.push_back(match.value()); - } - return results; + return MatchTitledUrlNodesWithQuery(sorted_nodes, query_nodes, max_count, + match_ancestor_titles); } void TitledUrlIndex::SortMatches(const TitledUrlNodeSet& matches, @@ -124,6 +126,27 @@ } } +std::vector<TitledUrlMatch> TitledUrlIndex::MatchTitledUrlNodesWithQuery( + const TitledUrlNodes& nodes, + const query_parser::QueryNodeVector& query_nodes, + size_t max_count, + bool match_ancestor_titles) { + // The highest typed counts should be at the beginning of the `matches` vector + // so that the best matches will always be included in the results. The loop + // that calculates match relevance in + // `HistoryContentsProvider::ConvertResults()` will run backwards to assure + // higher relevance will be attributed to the best matches. + std::vector<TitledUrlMatch> matches; + for (TitledUrlNodes::const_iterator i = nodes.begin(); + i != nodes.end() && matches.size() < max_count; ++i) { + absl::optional<TitledUrlMatch> match = + MatchTitledUrlNodeWithQuery(*i, query_nodes, match_ancestor_titles); + if (match) + matches.emplace_back(std::move(match).value()); + } + return matches; +} + absl::optional<TitledUrlMatch> TitledUrlIndex::MatchTitledUrlNodeWithQuery( const TitledUrlNode* node, const query_parser::QueryNodeVector& query_nodes, @@ -193,9 +216,7 @@ TitledUrlIndex::TitledUrlNodeSet TitledUrlIndex::RetrieveNodesMatchingAllTerms( const std::vector<std::u16string>& terms, query_parser::MatchingAlgorithm matching_algorithm) const { - if (terms.empty()) - return {}; - + DCHECK(!terms.empty()); TitledUrlNodeSet matches = RetrieveNodesMatchingTerm(terms[0], matching_algorithm); for (size_t i = 1; i < terms.size() && !matches.empty(); ++i) { @@ -210,20 +231,64 @@ TitledUrlIndex::TitledUrlNodeSet TitledUrlIndex::RetrieveNodesMatchingAnyTerms( const std::vector<std::u16string>& terms, - query_parser::MatchingAlgorithm matching_algorithm) const { - if (terms.empty()) - return {}; + query_parser::MatchingAlgorithm matching_algorithm, + size_t max_nodes) const { + DCHECK(!terms.empty()); - TitledUrlNodes matches = - RetrieveNodesMatchingTerm(terms[0], matching_algorithm); - for (size_t i = 1; i < terms.size(); ++i) { + std::vector<TitledUrlNodes> matches_per_term; + for (const std::u16string& term : terms) { + // Use `matching_algorithm`, as opposed to exact matching, to allow inputs + // like 'myFolder goog' to match a 'google.com' bookmark in a 'myFolder' + // folder. TitledUrlNodes term_matches = - RetrieveNodesMatchingTerm(terms[i], matching_algorithm); - std::copy(term_matches.begin(), term_matches.end(), - std::back_inserter(matches)); + RetrieveNodesMatchingTerm(term, matching_algorithm); + matches_per_term.push_back(std::move(term_matches)); } - return TitledUrlNodeSet(matches); + // Sort `matches_per_term` least frequent first. This prevents terms like + // 'https', which match a lot of nodes, from wasting `max_nodes` capacity. + base::ranges::sort( + matches_per_term, + [](size_t first, size_t second) { return first < second; }, + [](const auto& matches) { return matches.size(); }); + + // Use an `unordered_set` to avoid potentially 1000's of linear time + // insertions into the ordered `TitledUrlNodeSet` (i.e. `flat_set`). + std::unordered_set<const TitledUrlNode*> matches; + for (const auto& term_matches : matches_per_term) { + for (const TitledUrlNode* node : term_matches) { + matches.insert(node); + if (matches.size() == max_nodes) + break; + } + if (matches.size() == max_nodes) + break; + } + + // Append all nodes that match every input term. This is necessary because + // with the `max_nodes` threshold above, it's possible that `matches` is + // missing some nodes that match every input term. Since `matches_per_term[i]` + // is a superset of the intersection of `matches_per_term`s, if + // `matches_per_term[0].size() <= max_nodes`, all of `matches_per_term[0]`, + // and therefore the intersection matches`, are already in `matches`. + TitledUrlNodeSet all_term_matches; + if (matches_per_term[0].size() > max_nodes) { + all_term_matches = matches_per_term[0]; + for (size_t i = 1; i < matches_per_term.size() && !all_term_matches.empty(); + ++i) { + // Compute intersection between the two sets. + base::EraseIf(all_term_matches, + base::IsNotIn<TitledUrlNodeSet>(matches_per_term[i])); + } + // `all_term_matches` is the intersection of each term's node matches; the + // same as `RetrieveNodesMatchingAllTerms()`. We don't call the latter as a + // performance optimization. + DCHECK(all_term_matches == + RetrieveNodesMatchingAllTerms(terms, matching_algorithm)); + } + + matches.insert(all_term_matches.begin(), all_term_matches.end()); + return TitledUrlNodeSet(matches.begin(), matches.end()); } TitledUrlIndex::TitledUrlNodes TitledUrlIndex::RetrieveNodesMatchingTerm(
diff --git a/components/bookmarks/browser/titled_url_index.h b/components/bookmarks/browser/titled_url_index.h index 6730f5a9..477d883 100644 --- a/components/bookmarks/browser/titled_url_index.h +++ b/components/bookmarks/browser/titled_url_index.h
@@ -8,6 +8,7 @@ #include <stddef.h> #include <map> +#include <memory> #include <string> #include <vector> @@ -70,8 +71,9 @@ // For testing only. TitledUrlNodeSet RetrieveNodesMatchingAnyTermsForTesting( const std::vector<std::u16string>& terms, - query_parser::MatchingAlgorithm matching_algorithm) const { - return RetrieveNodesMatchingAnyTerms(terms, matching_algorithm); + query_parser::MatchingAlgorithm matching_algorithm, + size_t max_nodes) const { + return RetrieveNodesMatchingAnyTerms(terms, matching_algorithm, max_nodes); } private: @@ -83,6 +85,14 @@ void SortMatches(const TitledUrlNodeSet& matches, TitledUrlNodes* sorted_nodes) const; + // For each node, calls `MatchTitledUrlNodeWithQuery()` and returns the + // aggregated `TitledUrlMatch`s. + std::vector<TitledUrlMatch> MatchTitledUrlNodesWithQuery( + const TitledUrlNodes& nodes, + const query_parser::QueryNodeVector& query_nodes, + size_t max_count, + bool match_ancestor_titles); + // Finds |query_nodes| matches in |node| and returns a TitledUrlMatch // containing |node| and the matches. absl::optional<TitledUrlMatch> MatchTitledUrlNodeWithQuery( @@ -96,9 +106,16 @@ const std::vector<std::u16string>& terms, query_parser::MatchingAlgorithm matching_algorithm) const; + // Return matches for the specified `terms`. This is approximately a union of + // each term's match, with some limitations to avoid too many nodes being + // returned: terms shorter than `term_min_length` or matching more than + // `max_nodes_per_term` nodes won't have their nodes accumulated by union; and + // accumulation is capped to `max_nodes`. Guaranteed to include any node + // `RetrieveNodesMatchingAllTerms()` includes. TitledUrlNodeSet RetrieveNodesMatchingAnyTerms( const std::vector<std::u16string>& terms, - query_parser::MatchingAlgorithm matching_algorithm) const; + query_parser::MatchingAlgorithm matching_algorithm, + size_t max_nodes) const; // Return matches for the specified |term|. May return duplicates. TitledUrlNodes RetrieveNodesMatchingTerm(
diff --git a/components/bookmarks/browser/titled_url_index_unittest.cc b/components/bookmarks/browser/titled_url_index_unittest.cc index aef32e0..ff39e2f4 100644 --- a/components/bookmarks/browser/titled_url_index_unittest.cc +++ b/components/bookmarks/browser/titled_url_index_unittest.cc
@@ -236,6 +236,7 @@ {"abc def", "abc d", ""}, }; for (const TestData& test_data : data) { + SCOPED_TRACE("Query: " + test_data.query); ResetNodes(); for (const std::string& title : @@ -563,7 +564,7 @@ TEST_F(TitledUrlIndexTest, RetrieveNodesMatchingAllTerms) { TitledUrlNode* node = - AddNode("termA termB otherTerm xyz ab", GURL("http://foo.com")); + AddNode("term1 term2 other xyz ab", GURL("http://foo.com")); struct TestData { const std::string query; @@ -594,23 +595,24 @@ TEST_F(TitledUrlIndexTest, RetrieveNodesMatchingAnyTerms) { TitledUrlNode* node = - AddNode("termA termB otherTerm xyz ab", GURL("http://foo.com")); + AddNode("term1 term2 other xyz ab", GURL("http://foo.com")); struct TestData { const std::string query; const bool should_be_retrieved; - } data[] = {// Should return matches if any input terms match, even if not all - // node terms match. - {"term not", true}, - // Should not return duplicate matches. - {"term termA termB", true}, - // Should not early exit when there are no intermediate matches. - {"not term", true}, - // Should not match midword. - {"ther", false}, - // Short input terms should only return exact matches. - {"xy", false}, - {"ab", true}}; + } data[] = { + // Should return matches if any input terms match, even if not all node + // terms match. + {"term not", true}, + // Should not return duplicate matches. + {"term term1 term2", true}, + // Should not early exit when there are no intermediate matches. + {"not term", true}, + // Should not match midword. + {"ther", false}, + // Short input terms should only return exact matches. + {"xy", false}, + {"ab", true}}; for (const TestData& test_data : data) { SCOPED_TRACE("Query: " + test_data.query); @@ -618,7 +620,9 @@ base::SplitString(base::UTF8ToUTF16(test_data.query), u" ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); auto matches = index()->RetrieveNodesMatchingAnyTermsForTesting( - terms, query_parser::MatchingAlgorithm::DEFAULT); + terms, query_parser::MatchingAlgorithm::DEFAULT, 9); + + // Verify whether the node matched. if (test_data.should_be_retrieved) { EXPECT_EQ(matches.size(), 1u); EXPECT_TRUE(matches.contains(node)); @@ -627,6 +631,55 @@ }; } +TEST_F(TitledUrlIndexTest, RetrieveNodesMatchingAnyTermsMaxNodes) { + std::vector<TitledUrlNode*> nodes = { + AddNode("common11", GURL("http://foo.com")), + AddNode("common12", GURL("http://foo.com")), + AddNode("common13 uncommon", GURL("http://foo.com")), + AddNode("common21 uncommon1", GURL("http://foo.com")), + AddNode("common22 uncommon1", GURL("http://foo.com")), + AddNode("common23 uncommon1", GURL("http://foo.com")), + }; + + struct TestData { + const std::string query; + std::vector<int> retrieved_node_indexes; + } data[] = { + // Should not look for all-term matches if at least 1 term matches at most + // `max_nodes`. + {"uncommon1", {3, 4, 5}}, + // Like above, but even if some terms match more than `max_nodes`. Should + // look for per term matches even after `max_nodes` matches have been + // found. + {"common uncommon1", {3, 4, 5}}, + // Should look for all-term matches if all terms match more than + // `ma_nodes`. + {"uncommon", {2, 3, 4, 5}}, + {"common", {0, 1, 2, 3, 4, 5}}, + {"common uncommon", {2, 3, 4, 5}}, + {"common x", {0, 1, 2}}, + // Should not crash if no term has matches. + {"x", {}}, + }; + + for (const TestData& test_data : data) { + SCOPED_TRACE("Query: " + test_data.query); + std::vector<std::u16string> terms = + base::SplitString(base::UTF8ToUTF16(test_data.query), u" ", + base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); + auto matches = index()->RetrieveNodesMatchingAnyTermsForTesting( + terms, query_parser::MatchingAlgorithm::DEFAULT, 3); + + // Verify the correct nodes matched. + ASSERT_EQ(matches.size(), test_data.retrieved_node_indexes.size()); + for (int index : test_data.retrieved_node_indexes) { + SCOPED_TRACE("node: " + + base::UTF16ToUTF8(nodes[index]->GetTitledUrlNodeTitle())); + EXPECT_TRUE(matches.contains(nodes[index])); + } + }; +} + TEST_F(TitledUrlIndexTest, GetResultsMatchingAncestors) { TitledUrlNode* node = AddNode("leaf pare", GURL("http://foo.com"), "parent"); @@ -654,12 +707,14 @@ {"pa", true, false, false}, // Should not return matches if a term matches neither the title // nor ancestor. - {"term not parent", true, false, false}}; + {"leaf not parent", true, false, false}}; for (const TestData& test_data : data) { SCOPED_TRACE("Query: " + test_data.query); auto matches = GetResultsMatching(test_data.query, 10, test_data.match_ancestor_titles); + + // Verify whether the match. if (test_data.should_be_retrieved) { EXPECT_EQ(matches.size(), 1u); EXPECT_EQ(matches[0].node, node);
diff --git a/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareHelper.java b/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareHelper.java index 8688bbb..6884fa4e 100644 --- a/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareHelper.java +++ b/components/browser_ui/share/android/java/src/org/chromium/components/browser_ui/share/ShareHelper.java
@@ -181,8 +181,8 @@ sLastRegisteredReceiver.cancel(); } sLastRegisteredReceiver = new TargetChosenReceiver(callback); - context.registerReceiver( - sLastRegisteredReceiver, new IntentFilter(sTargetChosenReceiveAction)); + ContextUtils.registerNonExportedBroadcastReceiver(context, sLastRegisteredReceiver, + new IntentFilter(sTargetChosenReceiveAction)); } Intent intent = new Intent(sTargetChosenReceiveAction);
diff --git a/components/browser_ui/styles/android/java/res/color/chip_text_color_secondary.xml b/components/browser_ui/styles/android/java/res/color/chip_text_color_secondary.xml index 7483e90..0764d082 100644 --- a/components/browser_ui/styles/android/java/res/color/chip_text_color_secondary.xml +++ b/components/browser_ui/styles/android/java/res/color/chip_text_color_secondary.xml
@@ -6,10 +6,10 @@ <selector xmlns:android="http://schemas.android.com/apk/res/android"> <item android:alpha="@dimen/default_disabled_alpha" - android:color="@color/chip_text_color_selected" + android:color="@macro/default_text_color_on_accent2_container" android:state_selected="true" android:state_enabled="false" /> <item android:alpha="@dimen/default_disabled_alpha" android:color="@color/default_chip_assistive_text_color_secondary" android:state_enabled="false" /> - <item android:color="@color/chip_text_color_selected" android:state_selected="true" /> + <item android:color="@macro/default_text_color_on_accent2_container" android:state_selected="true" /> <item android:color="@color/default_chip_assistive_text_color_secondary" /> </selector>
diff --git a/components/browser_ui/styles/android/java/res/values-night/themes.xml b/components/browser_ui/styles/android/java/res/values-night/themes.xml index c171db4..22c6ea7 100644 --- a/components/browser_ui/styles/android/java/res/values-night/themes.xml +++ b/components/browser_ui/styles/android/java/res/values-night/themes.xml
@@ -10,6 +10,8 @@ <item name="colorOnPrimary">@color/baseline_primary_800</item> <item name="colorPrimaryContainer">@color/baseline_primary_700</item> <item name="colorOnPrimaryContainer">@color/baseline_primary_100</item> + <item name="colorSecondaryContainer">@color/baseline_secondary_700</item> + <item name="colorOnSecondaryContainer">@color/baseline_secondary_100</item> <item name="android:colorBackground">@color/baseline_neutral_900</item> <item name="colorOnBackground">@color/baseline_neutral_100</item> <item name="colorSurface">@color/baseline_neutral_900</item>
diff --git a/components/browser_ui/styles/android/java/res/values/colors.xml b/components/browser_ui/styles/android/java/res/values/colors.xml index 2cd5ba0..84e94c6 100644 --- a/components/browser_ui/styles/android/java/res/values/colors.xml +++ b/components/browser_ui/styles/android/java/res/values/colors.xml
@@ -46,6 +46,5 @@ <color name="progress_bar_secondary">@color/modern_grey_600</color> <!-- Chip Colors --> - <color name="chip_text_color_selected">@color/default_text_color_on_accent2_container</color> <color name="default_chip_assistive_text_color_secondary">@color/default_text_color_secondary</color> </resources>
diff --git a/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml b/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml index 340bec8..b2c7f8a9 100644 --- a/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml +++ b/components/browser_ui/styles/android/java/res/values/semantic_colors_dynamic.xml
@@ -20,6 +20,7 @@ <macro name="default_text_color">?attr/colorOnSurface</macro> <macro name="default_text_color_accent1">?attr/colorPrimary</macro> <macro name="default_text_color_on_accent1">?attr/colorOnPrimary</macro> + <macro name="default_text_color_on_accent2_container">?attr/colorOnSecondaryContainer</macro> <macro name="switch_enabled_unchecked_color_dark">?attr/colorOutline</macro> <macro name="switch_enabled_unchecked_color_light">?attr/colorOnSurface</macro> @@ -28,6 +29,13 @@ <macro name="hairline_stroke_color">?attr/colorOutline</macro> <macro name="divider_line_bg_color">?attr/colorSurfaceVariant</macro> + + <macro name="chip_bg_color">@macro/default_bg_color</macro> + <macro name="chip_bg_selected_color">?attr/colorSecondaryContainer</macro> + <macro name="chip_outline_color">?attr/colorOutline</macro> + <macro name="chip_outline_focused_color">?attr/colorOnSurface</macro> + <macro name="chip_state_layer_color">?attr/colorOnSurfaceVariant</macro> + <macro name="chip_state_layer_selected_color">?attr/colorOnSecondaryContainer</macro> --> <!-- Temporarily holdback @color version. Use for checkin. --> @@ -46,6 +54,7 @@ <macro name="default_text_color">@color/default_text_color_baseline</macro> <macro name="default_text_color_accent1">@color/default_text_color_blue_baseline</macro> <macro name="default_text_color_on_accent1">@color/default_text_color_on_accent1_baseline</macro> + <macro name="default_text_color_on_accent2_container">@color/default_text_color_on_accent2_container_baseline</macro> <macro name="switch_enabled_unchecked_color_dark">@color/switch_enabled_unchecked_color_baseline_dark</macro> <macro name="switch_enabled_unchecked_color_light">@color/switch_enabled_unchecked_color_baseline_light</macro> @@ -55,6 +64,13 @@ <macro name="hairline_stroke_color">@color/hairline_stroke_color_baseline</macro> <macro name="divider_line_bg_color">@color/divider_line_bg_color_baseline</macro> + <macro name="chip_bg_color">@color/default_bg_color_baseline</macro> + <macro name="chip_bg_selected_color">@color/chip_bg_selected_color_baseline</macro> + <macro name="chip_outline_color">@color/default_chip_outline_color</macro> + <macro name="chip_outline_focused_color">@color/chip_outline_focused_color_baseline</macro> + <macro name="chip_state_layer_color">@color/chip_state_layer_color_baseline</macro> + <macro name="chip_state_layer_selected_color">@color/chip_state_layer_selected_color_baseline</macro> + <!-- Gated by full dynamic colors param, no fallback needed. --> <macro name="circular_progress_icon_color_small_large">?attr/colorPrimary</macro> <macro name="circular_progress_outer_circle_progress_color_small">?attr/colorPrimary</macro>
diff --git a/components/browser_ui/styles/android/java/res/values/themes.xml b/components/browser_ui/styles/android/java/res/values/themes.xml index 072a9e81..34b5c84 100644 --- a/components/browser_ui/styles/android/java/res/values/themes.xml +++ b/components/browser_ui/styles/android/java/res/values/themes.xml
@@ -14,6 +14,8 @@ <item name="colorOnPrimary">@color/baseline_primary_0</item> <item name="colorPrimaryContainer">@color/baseline_primary_100</item> <item name="colorOnPrimaryContainer">@color/baseline_primary_900</item> + <item name="colorSecondaryContainer">@color/baseline_secondary_100</item> + <item name="colorOnSecondaryContainer">@color/baseline_secondary_900</item> <item name="colorAccent">@macro/default_control_color_active</item> <item name="android:colorBackground">@color/baseline_neutral_0</item> <item name="colorOnBackground">@color/baseline_neutral_900</item> @@ -60,6 +62,8 @@ <item name="colorOnPrimary">@color/baseline_primary_0</item> <item name="colorPrimaryContainer">@color/baseline_primary_100</item> <item name="colorOnPrimaryContainer">@color/baseline_primary_900</item> + <item name="colorSecondaryContainer">@color/baseline_secondary_100</item> + <item name="colorOnSecondaryContainer">@color/baseline_secondary_900</item> <item name="colorAccent">@macro/default_control_color_active</item> <item name="android:colorBackground">@color/baseline_neutral_0</item> <item name="colorOnBackground">@color/baseline_neutral_900</item>
diff --git a/components/browser_ui/widget/android/BUILD.gn b/components/browser_ui/widget/android/BUILD.gn index 99548de2..85faa15 100644 --- a/components/browser_ui/widget/android/BUILD.gn +++ b/components/browser_ui/widget/android/BUILD.gn
@@ -149,6 +149,7 @@ "java/res/anim/textbubble_out.xml", "java/res/color/chip_background_color.xml", "java/res/color/chip_ripple_color.xml", + "java/res/color/chip_state_layer_color.xml", "java/res/color/chip_stroke_color.xml", "java/res/color/chip_text_color.xml", "java/res/color/menu_chip_background.xml",
diff --git a/components/browser_ui/widget/android/java/res/color/chip_background_color.xml b/components/browser_ui/widget/android/java/res/color/chip_background_color.xml index ab034ff..c83bb19 100644 --- a/components/browser_ui/widget/android/java/res/color/chip_background_color.xml +++ b/components/browser_ui/widget/android/java/res/color/chip_background_color.xml
@@ -5,45 +5,13 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <!-- disabled --> - <item android:color="@color/chip_background_color_disabled" - android:state_enabled="false" /> - - <!-- hover --> - <item android:color="@color/chip_bg_color" - android:state_hovered="true"/> - - <!-- focused --> - <item android:color="@color/chip_focused" - android:state_focused="true" /> - - <!-- hover & focused --> - <item android:color="@color/chip_hover_focused" - android:state_focused="true" - android:state_hovered="true" /> + <item android:color="@android:color/transparent" android:state_enabled="false" /> <!-- selected --> - <item android:color="@color/chip_selected" + <item android:color="@macro/chip_bg_selected_color" android:state_selected="true" /> - <!-- selected & hover --> - <item - android:color="@color/chip_selected_hover" - android:state_hovered="true" - android:state_selected="true" /> - - <!-- selected & focused --> - <item - android:color="@color/chip_selected_focused" - android:state_selected="true" - android:state_focused="true" /> - - <!-- selected & hover & focused --> - <item - android:color="@color/chip_selected_hover_and_focused" - android:state_focused="true" - android:state_hovered="true" - android:state_selected="true" /> - <item android:color="@color/default_bg_color" /> + <!-- default state --> + <item android:color="@macro/chip_bg_color" /> </selector>
diff --git a/components/browser_ui/widget/android/java/res/color/chip_state_layer_color.xml b/components/browser_ui/widget/android/java/res/color/chip_state_layer_color.xml new file mode 100644 index 0000000..6e982360 --- /dev/null +++ b/components/browser_ui/widget/android/java/res/color/chip_state_layer_color.xml
@@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- Copyright 2022 The Chromium Authors. All rights reserved. + Use of this source code is governed by a BSD-style license that can be + found in the LICENSE file. +--> + +<!-- Translucent layer that will overlay the chip background based on the current state. This + separate layer is used to make overlaying dynamic colors easier. --> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + <!-- disabled --> + <item android:color="@android:color/transparent" + android:state_enabled="false" /> + + <!-- selected & pressed --> + <item android:alpha="@dimen/chip_state_layer_selected_pressed_alpha" android:color="@macro/chip_state_layer_selected_color" + android:state_pressed="true" + android:state_selected="true" /> + + <!-- selected & hover & focused --> + <!-- selected & focused --> + <item android:alpha="@dimen/chip_state_layer_selected_focused_alpha" android:color="@macro/chip_state_layer_selected_color" + android:state_selected="true" + android:state_focused="true" /> + + <!-- selected & hover --> + <item android:alpha="@dimen/chip_state_layer_selected_hover_alpha" android:color="@macro/chip_state_layer_selected_color" + android:state_hovered="true" + android:state_selected="true" /> + + <!-- pressed --> + <item android:alpha="@dimen/chip_state_layer_pressed_alpha" android:color="@macro/chip_state_layer_color" + android:state_pressed="true" /> + + <!-- hover & focused --> + <!-- focused --> + <item android:alpha="@dimen/chip_state_layer_focused_alpha" android:color="@macro/chip_state_layer_color" + android:state_focused="true" /> + + <!-- hover --> + <item android:alpha="@dimen/chip_state_layer_hover_alpha" android:color="@macro/chip_state_layer_color" + android:state_hovered="true"/> + + <!-- default state --> + <item android:color="@android:color/transparent"/> +</selector>
diff --git a/components/browser_ui/widget/android/java/res/color/chip_stroke_color.xml b/components/browser_ui/widget/android/java/res/color/chip_stroke_color.xml index 8661984a..d6fad8e 100644 --- a/components/browser_ui/widget/android/java/res/color/chip_stroke_color.xml +++ b/components/browser_ui/widget/android/java/res/color/chip_stroke_color.xml
@@ -5,8 +5,18 @@ --> <selector xmlns:android="http://schemas.android.com/apk/res/android"> - <item android:color="@color/hairline_stroke_color_baseline" - android:state_enabled="true" - android:state_selected="false" /> + <!-- disabled --> + <item android:alpha="@dimen/chip_outline_disabled_alpha" android:color="@macro/chip_outline_color" + android:state_enabled="false"/> + + <!-- unselected & focused --> + <item android:alpha="@dimen/chip_outline_focused_alpha" android:color="@macro/chip_outline_focused_color" + android:state_selected="false" + android:state_focused="true"/> + + <!-- unselected --> + <item android:alpha="@dimen/chip_outline_alpha" android:color="@macro/chip_outline_color" + android:state_selected="false"/> + <item android:color="@android:color/transparent" /> </selector>
diff --git a/components/browser_ui/widget/android/java/res/color/chip_text_color.xml b/components/browser_ui/widget/android/java/res/color/chip_text_color.xml index 19d10998..e1c0511d 100644 --- a/components/browser_ui/widget/android/java/res/color/chip_text_color.xml +++ b/components/browser_ui/widget/android/java/res/color/chip_text_color.xml
@@ -9,10 +9,10 @@ xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources"> <item android:alpha="@dimen/default_disabled_alpha" - android:color="@color/chip_text_color_selected" + android:color="@macro/default_text_color_on_accent2_container" android:state_selected="true" android:state_enabled="false"/> <item android:alpha="@dimen/default_disabled_alpha" android:color="@color/default_chip_assistive_text_color" android:state_enabled="false" /> - <item android:color="@color/chip_text_color_selected" android:state_selected="true" /> + <item android:color="@macro/default_text_color_on_accent2_container" android:state_selected="true" /> <item android:color="@color/default_chip_assistive_text_color" /> </selector>
diff --git a/components/browser_ui/widget/android/java/res/values-night/colors.xml b/components/browser_ui/widget/android/java/res/values-night/colors.xml index 7e3ca36..b0c3c92 100644 --- a/components/browser_ui/widget/android/java/res/values-night/colors.xml +++ b/components/browser_ui/widget/android/java/res/values-night/colors.xml
@@ -5,11 +5,11 @@ <resources> <!-- Chip colors --> - <color name="default_chip_outline_color">@color/default_chip_outline_color_dark</color> - <color name="chip_selected_hover">@color/chip_selected_hover_light</color> - <color name="chip_selected_focused">@color/chip_selected_focused_light</color> - <color name="chip_selected_hover_and_focused">@color/chip_selected_hover_and_focused_light</color> - <color name="chip_selected">@color/chip_selected_dark</color> + <color name="default_chip_outline_color">@color/default_chip_outline_color_light</color> + <color name="chip_bg_selected_color_baseline">@color/chip_bg_selected_color_dark</color> <color name="menu_chip_background_color">@color/menu_chip_background_color_light</color> <color name="menu_chip_background_color_disabled">@color/menu_chip_background_color_disabled_light</color> + <color name="chip_state_layer_color_baseline">@color/chip_state_layer_color_light</color> + <color name="chip_state_layer_selected_color_baseline">@color/chip_state_layer_selected_color_light</color> + <color name="chip_outline_focused_color_baseline">@color/chip_outline_focused_color_light</color> </resources>
diff --git a/components/browser_ui/widget/android/java/res/values-night/dimens.xml b/components/browser_ui/widget/android/java/res/values-night/dimens.xml index 38ea4d9e..2687621 100644 --- a/components/browser_ui/widget/android/java/res/values-night/dimens.xml +++ b/components/browser_ui/widget/android/java/res/values-night/dimens.xml
@@ -9,5 +9,7 @@ <dimen name="sheet_background_elev">@dimen/default_elevation_4</dimen> <!-- Chips default measures --> - <dimen name="chip_background_selected_alpha">@dimen/chip_background_selected_alpha_dark</dimen> + <dimen name="chip_state_layer_hover_alpha">@dimen/chip_state_layer_hover_alpha_dark</dimen> + <dimen name="chip_state_layer_focused_alpha">@dimen/chip_state_layer_focused_alpha_dark</dimen> + <dimen name="chip_state_layer_pressed_alpha">@dimen/chip_state_layer_pressed_alpha_dark</dimen> </resources>
diff --git a/components/browser_ui/widget/android/java/res/values/attrs.xml b/components/browser_ui/widget/android/java/res/values/attrs.xml index bcadf542..e7885c98 100644 --- a/components/browser_ui/widget/android/java/res/values/attrs.xml +++ b/components/browser_ui/widget/android/java/res/values/attrs.xml
@@ -96,6 +96,7 @@ <attr name="textAlignStart" format="boolean"/> <attr name="reduceTextStartPadding" format="boolean"/> <attr name="chipColor" format="color"/> + <attr name="chipStateLayerColor" format="color"/> <attr name="chipStrokeColor" format="color"/> <attr name="chipStyle" format="reference"/> <attr name="cornerRadius" format="dimension"/>
diff --git a/components/browser_ui/widget/android/java/res/values/colors.xml b/components/browser_ui/widget/android/java/res/values/colors.xml index a0b7e7e..f9473ad 100644 --- a/components/browser_ui/widget/android/java/res/values/colors.xml +++ b/components/browser_ui/widget/android/java/res/values/colors.xml
@@ -11,32 +11,27 @@ <!-- Chip Colors --> <color name="default_chip_assistive_text_color">@color/default_text_color_baseline</color> - <color name="chip_bg_color">@color/default_bg_color</color> - <color name="chip_background_color_disabled">@android:color/transparent</color> <color name="default_chip_ripple_color">@color/default_bg_color_elev_2_baseline</color> - <color name="chip_focused">@color/default_bg_color_elev_4_baseline</color> - <color name="chip_hover_focused">@color/default_bg_color_elev_4_baseline</color> - - <!-- Same as ?attr/colorOutline. --> - <color name="default_chip_outline_color_light">@color/baseline_neutral_variant_200</color> - <color name="default_chip_outline_color_dark">@color/baseline_neutral_variant_500</color> - <color name="default_chip_outline_color" tools:ignore="UnusedResources">@color/default_chip_outline_color_light</color> - <!-- Mix of ?attr/colorSecondaryContainer and ?attr/colorOnSurface. --> - <color name="chip_selected_hover_light">@color/baseline_secondary_300_with_neutral_100_alpha_8</color> - <color name="chip_selected_hover_dark">@color/baseline_secondary_100_with_neutral_900_alpha_8</color> - <color name="chip_selected_hover">@color/chip_selected_hover_dark</color> - <!-- Mix of ?attr/colorSecondaryContainer and ?attr/colorOnSurface. --> - <color name="chip_selected_focused_light">@color/baseline_secondary_300_with_neutral_100_alpha_24</color> - <color name="chip_selected_focused_dark">@color/baseline_secondary_100_with_neutral_900_alpha_24</color> - <color name="chip_selected_focused">@color/chip_selected_focused_dark</color> - <!-- Mix of ?attr/colorSecondaryContainer and ?attr/colorOnSurface. --> - <color name="chip_selected_hover_and_focused_light">@color/baseline_secondary_300_with_neutral_100_alpha_24</color> - <color name="chip_selected_hover_and_focused_dark">@color/baseline_secondary_100_with_neutral_900_alpha_24</color> - <color name="chip_selected_hover_and_focused">@color/chip_selected_hover_and_focused_dark</color> <!-- Same as ?attr/colorSecondaryContainer --> - <color name="chip_selected_light">@color/baseline_secondary_100</color> - <color name="chip_selected_dark">@color/baseline_secondary_300</color> - <color name="chip_selected">@color/chip_selected_light</color> + <color name="chip_bg_selected_color_light">@color/baseline_secondary_100</color> + <color name="chip_bg_selected_color_dark">@color/baseline_secondary_700</color> + <color name="chip_bg_selected_color_baseline" tools:ignore="UnusedResources">@color/chip_bg_selected_color_light</color> + <!-- Same as ?attr/colorOnSurfaceVariant --> + <color name="chip_state_layer_color_dark">@color/baseline_neutral_variant_700</color> + <color name="chip_state_layer_color_light">@color/baseline_neutral_variant_200</color> + <color name="chip_state_layer_color_baseline" tools:ignore="UnusedResources">@color/chip_state_layer_color_dark</color> + <!-- Same as ?attr/colorOnSecondaryContainer --> + <color name="chip_state_layer_selected_color_dark">@color/baseline_secondary_900</color> + <color name="chip_state_layer_selected_color_light">@color/baseline_secondary_100</color> + <color name="chip_state_layer_selected_color_baseline" tools:ignore="UnusedResources">@color/chip_state_layer_selected_color_dark</color> + <!-- Same as ?attr/colorOutline. --> + <color name="default_chip_outline_color_light">@color/baseline_neutral_variant_400</color> + <color name="default_chip_outline_color_dark">@color/baseline_neutral_variant_500</color> + <color name="default_chip_outline_color" tools:ignore="UnusedResources">@color/default_chip_outline_color_dark</color> + <!-- Same as ?attr/colorOnSurface --> + <color name="chip_outline_focused_color_dark">@color/baseline_neutral_900</color> + <color name="chip_outline_focused_color_light">@color/baseline_neutral_100</color> + <color name="chip_outline_focused_color_baseline" tools:ignore="UnusedResources">@color/chip_outline_focused_color_dark</color> <color name="menu_chip_background_color_dark">@color/modern_blue_600_alpha_6</color> <color name="menu_chip_background_color_light">@color/modern_blue_300_alpha_10</color>
diff --git a/components/browser_ui/widget/android/java/res/values/dimens.xml b/components/browser_ui/widget/android/java/res/values/dimens.xml index c827e63..b19bd92 100644 --- a/components/browser_ui/widget/android/java/res/values/dimens.xml +++ b/components/browser_ui/widget/android/java/res/values/dimens.xml
@@ -141,8 +141,22 @@ <dimen name="tile_view_title_margin_top_modern">61dp</dimen> <!-- Chips default measures --> - <item name="chip_background_selected_alpha_light" format="float" type="dimen">0.06</item> - <item name="chip_background_selected_alpha_dark" format="float" type="dimen">1</item> + <item name="chip_outline_alpha" format="float" type="dimen">0.8</item> + <item name="chip_outline_disabled_alpha" format="float" type="dimen">0.12</item> + <item name="chip_outline_focused_alpha" format="float" type="dimen">1</item> + + <item name="chip_state_layer_hover_alpha_light" format="float" type="dimen">0.08</item> + <item name="chip_state_layer_hover_alpha_dark" format="float" type="dimen">0.16</item> + <item name="chip_state_layer_hover_alpha" format="float" type="dimen">@dimen/chip_state_layer_hover_alpha_light</item> + <item name="chip_state_layer_focused_alpha_light" format="float" type="dimen">0.12</item> + <item name="chip_state_layer_focused_alpha_dark" format="float" type="dimen">0.24</item> + <item name="chip_state_layer_focused_alpha" format="float" type="dimen">@dimen/chip_state_layer_focused_alpha_light</item> + <item name="chip_state_layer_pressed_alpha_light" format="float" type="dimen">0.12</item> + <item name="chip_state_layer_pressed_alpha_dark" format="float" type="dimen">0.20</item> + <item name="chip_state_layer_pressed_alpha" format="float" type="dimen">@dimen/chip_state_layer_pressed_alpha_light</item> + <item name="chip_state_layer_selected_hover_alpha" format="float" type="dimen">0.08</item> + <item name="chip_state_layer_selected_focused_alpha" format="float" type="dimen">0.12</item> + <item name="chip_state_layer_selected_pressed_alpha" format="float" type="dimen">0.12</item> <dimen name="chip_solid_border_width">0dp</dimen> <dimen name="chip_border_width">1dp</dimen> @@ -153,7 +167,6 @@ <dimen name="chip_element_leading_padding">8dp</dimen> <dimen name="chip_element_extended_leading_padding">16dp</dimen> <dimen name="chip_bg_vertical_inset">8dp</dimen> - <dimen name="chip_background_selected_alpha" tools:ignore="UnusedResources">@dimen/chip_background_selected_alpha_light</dimen> <dimen name="chip_icon_size">20dp</dimen> <dimen name="chip_loading_view_size">12dp</dimen> <dimen name="chip_end_icon_margin_start">8dp</dimen>
diff --git a/components/browser_ui/widget/android/java/res/values/styles.xml b/components/browser_ui/widget/android/java/res/values/styles.xml index 475c2a7..c968dbb 100644 --- a/components/browser_ui/widget/android/java/res/values/styles.xml +++ b/components/browser_ui/widget/android/java/res/values/styles.xml
@@ -156,6 +156,7 @@ <item name="android:gravity">center_vertical</item> <item name="android:orientation">horizontal</item> <item name="chipColor">@color/chip_background_color</item> + <item name="chipStateLayerColor">@color/chip_state_layer_color</item> <item name="primaryTextAppearance">@style/TextAppearance.ChipText</item> <item name="secondaryTextAppearance">@style/TextAppearance.ChipHint</item> <item name="rippleColor">@color/chip_ripple_color</item>
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java index 0b45cfc1..5dd8ef6 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/ContextMenuDialog.java
@@ -10,8 +10,10 @@ import android.graphics.drawable.ColorDrawable; import android.os.Build; import android.provider.Settings; +import android.view.DragEvent; import android.view.MotionEvent; import android.view.View; +import android.view.View.OnDragListener; import android.view.View.OnLayoutChangeListener; import android.view.ViewGroup.LayoutParams; import android.view.Window; @@ -55,6 +57,7 @@ private @Nullable AnchoredPopupWindow mPopupWindow; private View mLayout; private OnLayoutChangeListener mOnLayoutChangeListener; + private OnDragListener mOnDragListener; private int mTopMarginPx; private int mBottomMarginPx; @@ -203,6 +206,17 @@ } }; (mIsPopup ? mLayout : mContentView).addOnLayoutChangeListener(mOnLayoutChangeListener); + + // Forward the drag events to delegate view if drag happens on top of container. + if (isDialogNonModal()) { + mOnDragListener = new OnDragListener() { + @Override + public boolean onDrag(View view, DragEvent dragEvent) { + return mTouchEventDelegateView.dispatchDragEvent(dragEvent); + } + }; + mLayout.setOnDragListener(mOnDragListener); + } } private void startEnterAnimation() { @@ -236,6 +250,10 @@ mLayout.removeOnLayoutChangeListener(mOnLayoutChangeListener); mOnLayoutChangeListener = null; } + if (mOnDragListener != null) { + mLayout.setOnDragListener(null); + mOnDragListener = null; + } super.dismiss(); return; @@ -275,7 +293,7 @@ dismiss(); return true; } - if (mIsPopup && mShouldRemoveScrim && mTouchEventDelegateView != null) { + if (isDialogNonModal()) { return mTouchEventDelegateView.dispatchTouchEvent(event); } return false; @@ -308,4 +326,8 @@ animation.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN_INTERPOLATOR); return animation; } + + private boolean isDialogNonModal() { + return mIsPopup && mShouldRemoveScrim && mTouchEventDelegateView != null; + } }
diff --git a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/chips/ChipView.java b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/chips/ChipView.java index a052ac12..628099b 100644 --- a/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/chips/ChipView.java +++ b/components/browser_ui/widget/android/java/src/org/chromium/components/browser_ui/widget/chips/ChipView.java
@@ -113,6 +113,8 @@ solidColorChip ? R.dimen.chip_solid_border_width : R.dimen.chip_border_width; int chipColorId = a.getResourceId(R.styleable.ChipView_chipColor, R.color.chip_background_color); + int chipStateLayerColorId = a.getResourceId( + R.styleable.ChipView_chipStateLayerColor, R.color.chip_state_layer_color); int rippleColorId = a.getResourceId(R.styleable.ChipView_rippleColor, R.color.chip_ripple_color); int chipStrokeColorId = @@ -196,8 +198,9 @@ addView(mPrimaryText); // Reset icon and background: - mRippleBackgroundHelper = new RippleBackgroundHelper(this, chipColorId, rippleColorId, - mCornerRadius, chipStrokeColorId, chipBorderWidthId, verticalInset); + mRippleBackgroundHelper = + new RippleBackgroundHelper(this, chipColorId, chipStateLayerColorId, rippleColorId, + mCornerRadius, chipStrokeColorId, chipBorderWidthId, verticalInset); setIcon(INVALID_ICON_ID, false); }
diff --git a/components/cronet/native/perftest/perf_test.cc b/components/cronet/native/perftest/perf_test.cc index 95aa14e..1633280 100644 --- a/components/cronet/native/perftest/perf_test.cc +++ b/components/cronet/native/perftest/perf_test.cc
@@ -62,9 +62,9 @@ // Return an int configuration option. int GetConfigInt(const char* key) { - int value; - CHECK(g_options->GetInteger(key, &value)) << "Cannot find key: " << key; - return value; + absl::optional<int> config = g_options->FindIntKey(key); + CHECK(config) << "Cannot find key: " << key; + return *config; } // Put together a benchmark configuration into a benchmark name.
diff --git a/components/embedder_support/user_agent_utils.cc b/components/embedder_support/user_agent_utils.cc index 1ea77d0..97c0f2b3 100644 --- a/components/embedder_support/user_agent_utils.cc +++ b/components/embedder_support/user_agent_utils.cc
@@ -300,6 +300,9 @@ LOG(WARNING) << "Ignored invalid value for flag --" << kUserAgent; } + if (base::FeatureList::IsEnabled(blink::features::kFullUserAgent)) + return GetFullUserAgent(); + if (base::FeatureList::IsEnabled(blink::features::kReduceUserAgent)) return GetReducedUserAgent(force_major_to_minor);
diff --git a/components/embedder_support/user_agent_utils_unittest.cc b/components/embedder_support/user_agent_utils_unittest.cc index 60d04313..383b37b 100644 --- a/components/embedder_support/user_agent_utils_unittest.cc +++ b/components/embedder_support/user_agent_utils_unittest.cc
@@ -459,6 +459,29 @@ EXPECT_EQ(GetUserAgent(), GetReducedUserAgent()); } +TEST_F(UserAgentUtilsTest, UserAgentStringFull) { + base::test::ScopedFeatureList scoped_feature_list; + + // Verify that the full user agent string respects + // --force-major-version-to-minor + scoped_feature_list.Reset(); + scoped_feature_list.InitWithFeatures( + {blink::features::kFullUserAgent, + blink::features::kForceMajorVersionInMinorPositionInUserAgent}, + {}); + { EXPECT_EQ(GetUserAgent(), GetFullUserAgent()); } + + // Verify that the full user agent string when both reduced and full UA + // feature enabled respects + // --force-major-version-to-minor + scoped_feature_list.Reset(); + scoped_feature_list.InitWithFeatures( + {blink::features::kFullUserAgent, blink::features::kReduceUserAgent, + blink::features::kForceMajorVersionInMinorPositionInUserAgent}, + {}); + { EXPECT_EQ(GetUserAgent(), GetFullUserAgent()); } +} + TEST_F(UserAgentUtilsTest, UserAgentMetadata) { auto metadata = GetUserAgentMetadata();
diff --git a/components/feed/feed_feature_list.cc b/components/feed/feed_feature_list.cc index cab079c..ade51cc6 100644 --- a/components/feed/feed_feature_list.cc +++ b/components/feed/feed_feature_list.cc
@@ -86,6 +86,10 @@ "EnableOpenInNewTabFromStartSurfaceFeed", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kWebUiFeed{"FeedWebUi", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::FeatureParam<std::string> kWebUiScriptFetchUrl{ + &kWebUiFeed, "scripturl", "chrome-untrusted://feed/feed.js"}; + std::string GetFeedReferrerUrl() { const base::Feature* feature = base::FeatureList::IsEnabled(kInterestFeedV2) ? &kInterestFeedV2
diff --git a/components/feed/feed_feature_list.h b/components/feed/feed_feature_list.h index 84e6254..ad19c613 100644 --- a/components/feed/feed_feature_list.h +++ b/components/feed/feed_feature_list.h
@@ -92,6 +92,10 @@ // on Start Surface. extern const base::Feature kEnableOpenInNewTabFromStartSurfaceFeed; +// Feature that causes the WebUI version of the Feed to be enabled. +extern const base::Feature kWebUiFeed; +extern const base::FeatureParam<std::string> kWebUiScriptFetchUrl; + std::string GetFeedReferrerUrl(); } // namespace feed
diff --git a/components/guest_view/browser/guest_view_base.cc b/components/guest_view/browser/guest_view_base.cc index 920e032..9044cb6 100644 --- a/components/guest_view/browser/guest_view_base.cc +++ b/components/guest_view/browser/guest_view_base.cc
@@ -239,7 +239,8 @@ GetGuestViewManager()->AddGuest(guest_instance_id_, guest_web_contents); // Populate the view instance ID if we have it on creation. - create_params.GetInteger(kParameterInstanceId, &view_instance_id_); + view_instance_id_ = create_params.FindIntKey(kParameterInstanceId) + .value_or(view_instance_id_); SetUpSizing(create_params); @@ -466,7 +467,8 @@ void GuestViewBase::SetAttachParams(const base::DictionaryValue& params) { attach_params_.reset(params.DeepCopy()); - attach_params_->GetInteger(kParameterInstanceId, &view_instance_id_); + view_instance_id_ = attach_params_->FindIntKey(kParameterInstanceId) + .value_or(view_instance_id_); } void GuestViewBase::SetOpener(GuestViewBase* guest) { @@ -816,15 +818,15 @@ params.FindBoolKey(kAttributeAutoSize); bool auto_size_enabled = auto_size_enabled_opt.value_or(auto_size_enabled_); - int max_height = max_auto_size_.height(); - int max_width = max_auto_size_.width(); - params.GetInteger(kAttributeMaxHeight, &max_height); - params.GetInteger(kAttributeMaxWidth, &max_width); + int max_height = + params.FindIntKey(kAttributeMaxHeight).value_or(max_auto_size_.height()); + int max_width = + params.FindIntKey(kAttributeMaxWidth).value_or(max_auto_size_.width()); - int min_height = min_auto_size_.height(); - int min_width = min_auto_size_.width(); - params.GetInteger(kAttributeMinHeight, &min_height); - params.GetInteger(kAttributeMinWidth, &min_width); + int min_height = + params.FindIntKey(kAttributeMinHeight).value_or(min_auto_size_.height()); + int min_width = + params.FindIntKey(kAttributeMinWidth).value_or(min_auto_size_.width()); double element_height = params.FindDoublePath(kElementHeight).value_or(0.0); double element_width = params.FindDoublePath(kElementWidth).value_or(0.0);
diff --git a/components/login/base_screen_handler_utils.h b/components/login/base_screen_handler_utils.h index dd69713..f050e16e 100644 --- a/components/login/base_screen_handler_utils.h +++ b/components/login/base_screen_handler_utils.h
@@ -45,10 +45,10 @@ template <typename T> inline bool GetArg(const base::ListValue* args, size_t index, T* out_value) { - const base::Value* value; - if (!args->Get(index, &value)) + const auto& list = args->GetListDeprecated(); + if (list.size() <= index) return false; - return ParseValue(value, out_value); + return ParseValue(&list[index], out_value); } base::Value LOGIN_EXPORT MakeValue(bool v);
diff --git a/components/network_session_configurator/browser/network_session_configurator_unittest.cc b/components/network_session_configurator/browser/network_session_configurator_unittest.cc index 1d1c4fbd..2c38258 100644 --- a/components/network_session_configurator/browser/network_session_configurator_unittest.cc +++ b/components/network_session_configurator/browser/network_session_configurator_unittest.cc
@@ -32,47 +32,6 @@ namespace network_session_configurator { -namespace { - -// TODO(haoyuewang) Move this method to third_party/quic/core/quic_versions.h. -// Compare two sets of QUIC versions, considering versions with identical ALPN -// string to be equal, ignoring duplicates and ordering. -bool QuicVersionVectorsEqual(const quic::ParsedQuicVersionVector& versions1, - const quic::ParsedQuicVersionVector& versions2) { - // Collect ALPN tokens. - std::vector<std::string> alpn1; - for (const auto& version : versions1) { - alpn1.push_back(quic::AlpnForVersion(version)); - } - // Sort and deduplicate. - std::sort(alpn1.begin(), alpn1.end()); - auto last = std::unique(alpn1.begin(), alpn1.end()); - if (last != alpn1.end()) { - alpn1.erase(last, alpn1.end()); - } - - // Collect ALPN tokens. - std::vector<std::string> alpn2; - for (const auto& version : versions2) { - alpn2.push_back(quic::AlpnForVersion(version)); - } - // Sort and deduplicate. - std::sort(alpn2.begin(), alpn2.end()); - last = std::unique(alpn2.begin(), alpn2.end()); - if (last != alpn2.end()) { - alpn2.erase(last, alpn2.end()); - } - - // Compare. - if (alpn1.size() != alpn2.size()) { - return false; - } - - return std::equal(alpn1.begin(), alpn1.end(), alpn2.begin()); -} - -} // namespace - class NetworkSessionConfiguratorTest : public testing::Test { public: NetworkSessionConfiguratorTest() @@ -604,8 +563,7 @@ ParseFieldTrials(); quic::ParsedQuicVersionVector supported_versions = {version1, version2}; - EXPECT_TRUE(QuicVersionVectorsEqual(supported_versions, - quic_params_.supported_versions)); + EXPECT_EQ(supported_versions, quic_params_.supported_versions); } TEST_F(NetworkSessionConfiguratorTest, @@ -982,8 +940,7 @@ quic::AlpnForVersion(version_)); ParseCommandLineAndFieldTrials(command_line); quic::ParsedQuicVersionVector expected_versions = {version_}; - EXPECT_TRUE(QuicVersionVectorsEqual(expected_versions, - quic_params_.supported_versions)); + EXPECT_EQ(expected_versions, quic_params_.supported_versions); } TEST_P(NetworkSessionConfiguratorWithQuicVersionTest, @@ -1029,8 +986,7 @@ base::FieldTrialList::CreateFieldTrial("QUIC", "Enabled"); ParseFieldTrials(); quic::ParsedQuicVersionVector expected_versions = {version_}; - EXPECT_TRUE(QuicVersionVectorsEqual(expected_versions, - quic_params_.supported_versions)); + EXPECT_EQ(expected_versions, quic_params_.supported_versions); } TEST_P(NetworkSessionConfiguratorWithQuicVersionTest, ObsoleteQuicVersion) {
diff --git a/components/omnibox/browser/actions/omnibox_pedal.cc b/components/omnibox/browser/actions/omnibox_pedal.cc index 89238fb..1a81d183 100644 --- a/components/omnibox/browser/actions/omnibox_pedal.cc +++ b/components/omnibox/browser/actions/omnibox_pedal.cc
@@ -252,13 +252,16 @@ DCHECK(ui_strings.is_dict()); // The pedal_processor tool ensures that this dictionary is either omitted, // or else included with all these keys populated. - ui_strings.FindKey("button_text")->GetAsString(&strings_.hint); - ui_strings.FindKey("description_text") - ->GetAsString(&strings_.suggestion_contents); - ui_strings.FindKey("spoken_button_focus_announcement") - ->GetAsString(&strings_.accessibility_hint); - ui_strings.FindKey("spoken_suggestion_description_suffix") - ->GetAsString(&strings_.accessibility_suffix); + if (const std::string* string = ui_strings.FindStringKey("button_text")) + strings_.hint = base::UTF8ToUTF16(*string); + if (const std::string* string = ui_strings.FindStringKey("description_text")) + strings_.suggestion_contents = base::UTF8ToUTF16(*string); + if (const std::string* string = + ui_strings.FindStringKey("spoken_button_focus_announcement")) + strings_.accessibility_hint = base::UTF8ToUTF16(*string); + if (const std::string* string = + ui_strings.FindStringKey("spoken_suggestion_description_suffix")) + strings_.accessibility_suffix = base::UTF8ToUTF16(*string); #if BUILDFLAG(IS_ANDROID) CreateOrUpdateJavaObject(); #endif
diff --git a/components/omnibox/browser/actions/omnibox_pedal_provider.cc b/components/omnibox/browser/actions/omnibox_pedal_provider.cc index fcf66b3..63ff316 100644 --- a/components/omnibox/browser/actions/omnibox_pedal_provider.cc +++ b/components/omnibox/browser/actions/omnibox_pedal_provider.cc
@@ -299,7 +299,8 @@ int token_id = 0; for (const auto& token_value : dictionary) { std::u16string token; - token_value.GetAsString(&token); + if (token_value.is_string()) + token = base::UTF8ToUTF16(token_value.GetString()); dictionary_.insert({token, token_id}); ++token_id; }
diff --git a/components/omnibox/browser/bookmark_provider_unittest.cc b/components/omnibox/browser/bookmark_provider_unittest.cc index 9294427..43ffff8 100644 --- a/components/omnibox/browser/bookmark_provider_unittest.cc +++ b/components/omnibox/browser/bookmark_provider_unittest.cc
@@ -153,8 +153,8 @@ return positions; } -// Convience function to make comparing test expectations structure against the -// actual ACMatchClassifications easier. +// Convenience function to make comparing test expectations structure against +// the actual ACMatchClassifications easier. TestBookmarkPositions PositionsFromExpectations( const size_t expectations[9][2]) { TestBookmarkPositions positions;
diff --git a/components/optimization_guide/core/tflite_op_resolver.cc b/components/optimization_guide/core/tflite_op_resolver.cc index 1cd89433..8674eb8 100644 --- a/components/optimization_guide/core/tflite_op_resolver.cc +++ b/components/optimization_guide/core/tflite_op_resolver.cc
@@ -371,6 +371,10 @@ tflite::ops::builtin::Register_BATCH_MATMUL(), /* min_version = */ 1, /* max_version = */ 4); + AddBuiltin(tflite::BuiltinOperator_GELU, + tflite::ops::builtin::Register_GELU(), + /* min_version = */ 1, + /* max_version = */ 2); } } // namespace optimization_guide
diff --git a/components/optimization_guide/features.gni b/components/optimization_guide/features.gni index b7407c5..2ed17e31 100644 --- a/components/optimization_guide/features.gni +++ b/components/optimization_guide/features.gni
@@ -16,6 +16,7 @@ # # If changing the value of this, you MUST also update the following files depending on the # platform: + # ChromeOS: //lib/chrome_util.py in the Chromite repo (ex: https://crrev.com/c/3437291) # Linux: Internal archive files. //chrome/installer/linux/common/installer.include handles the # relevant files not being present. # Mac: //chrome/installer/mac/signing/parts.py
diff --git a/components/optimization_guide/proto/models.proto b/components/optimization_guide/proto/models.proto index 43784f1f..a916421 100644 --- a/components/optimization_guide/proto/models.proto +++ b/components/optimization_guide/proto/models.proto
@@ -302,6 +302,9 @@ MODEL_ENGINE_VERSION_TFLITE_2_8 = 6; // A model using only operations that are supported by TensorflowLite 2.9.0. MODEL_ENGINE_VERSION_TFLITE_2_9 = 7; + // A model using only operations that are supported by TensorflowLite 2.9.0. + // This adds GELU to the supported ops in Optimiziation Guide. + MODEL_ENGINE_VERSION_TFLITE_2_9_0_1 = 8; } // A set of model features and the host that it applies to.
diff --git a/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc b/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc index a9b60b4..5e26ad0 100644 --- a/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc +++ b/components/paint_preview/renderer/paint_preview_recorder_browsertest.cc
@@ -21,6 +21,7 @@ #include "third_party/blink/public/platform/web_runtime_features.h" #include "third_party/blink/public/web/web_local_frame.h" #include "third_party/blink/public/web/web_testing_support.h" +#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkPicture.h" #include "ui/native_theme/native_theme_features.h"
diff --git a/components/policy/core/common/generate_policy_source_unittest.cc b/components/policy/core/common/generate_policy_source_unittest.cc index c2249ec..543afdf 100644 --- a/components/policy/core/common/generate_policy_source_unittest.cc +++ b/components/policy/core/common/generate_policy_source_unittest.cc
@@ -232,7 +232,7 @@ const base::Value* multiprof_behavior = policy_map.GetValue(key::kChromeOsMultiProfileUserBehavior); base::Value expected("primary-only"); - EXPECT_TRUE(expected.Equals(multiprof_behavior)); + EXPECT_EQ(expected, *multiprof_behavior); // If policy already configured, it's not changed to enterprise defaults. policy_map.Set(key::kChromeOsMultiProfileUserBehavior, POLICY_LEVEL_MANDATORY, @@ -242,7 +242,7 @@ multiprof_behavior = policy_map.GetValue(key::kChromeOsMultiProfileUserBehavior); expected = base::Value("test_value"); - EXPECT_TRUE(expected.Equals(multiprof_behavior)); + EXPECT_EQ(expected, *multiprof_behavior); } TEST(GeneratePolicySource, SetEnterpriseSystemWideDefaults) {
diff --git a/components/prefs/in_memory_pref_store_unittest.cc b/components/prefs/in_memory_pref_store_unittest.cc index 4ad18640..81fcf83 100644 --- a/components/prefs/in_memory_pref_store_unittest.cc +++ b/components/prefs/in_memory_pref_store_unittest.cc
@@ -36,9 +36,9 @@ store_->SetValue(kTestPref, std::make_unique<base::Value>(42), WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_TRUE(store_->GetValue(kTestPref, &value)); - EXPECT_TRUE(base::Value(42).Equals(value)); + EXPECT_EQ(base::Value(42), *value); EXPECT_TRUE(store_->GetMutableValue(kTestPref, &mutable_value)); - EXPECT_TRUE(base::Value(42).Equals(mutable_value)); + EXPECT_EQ(base::Value(42), *mutable_value); store_->RemoveValue(kTestPref, WriteablePrefStore::DEFAULT_PREF_WRITE_FLAGS); EXPECT_FALSE(store_->GetValue(kTestPref, &value));
diff --git a/components/prefs/json_pref_store_unittest.cc b/components/prefs/json_pref_store_unittest.cc index 3082f81..6deeb68 100644 --- a/components/prefs/json_pref_store_unittest.cc +++ b/components/prefs/json_pref_store_unittest.cc
@@ -388,9 +388,9 @@ // Check values. const Value* result = nullptr; EXPECT_TRUE(pref_store->GetValue("list", &result)); - EXPECT_TRUE(ListValue().Equals(result)); + EXPECT_EQ(ListValue(), *result); EXPECT_TRUE(pref_store->GetValue("dict", &result)); - EXPECT_TRUE(DictionaryValue().Equals(result)); + EXPECT_EQ(DictionaryValue(), *result); } // This test is just documenting some potentially non-obvious behavior. It
diff --git a/components/prefs/scoped_user_pref_update_unittest.cc b/components/prefs/scoped_user_pref_update_unittest.cc index fb706f9..18eaa51 100644 --- a/components/prefs/scoped_user_pref_update_unittest.cc +++ b/components/prefs/scoped_user_pref_update_unittest.cc
@@ -57,7 +57,7 @@ // Modifications happen online and are instantly visible, though. const base::Value* current_value = prefs_.GetDictionary(kPref); ASSERT_TRUE(current_value); - EXPECT_TRUE(expected_dictionary.Equals(current_value)); + EXPECT_EQ(expected_dictionary, *current_value); // Now we are leaving the scope of the update so we should be notified. observer_.Expect(kPref, &expected_dictionary); @@ -66,7 +66,7 @@ const base::Value* current_value = prefs_.GetDictionary(kPref); ASSERT_TRUE(current_value); - EXPECT_TRUE(expected_dictionary.Equals(current_value)); + EXPECT_EQ(expected_dictionary, *current_value); } TEST_F(ScopedUserPrefUpdateTest, NeverTouchAnything) {
diff --git a/components/prefs/segregated_pref_store_unittest.cc b/components/prefs/segregated_pref_store_unittest.cc index fb43dd29..4014acd 100644 --- a/components/prefs/segregated_pref_store_unittest.cc +++ b/components/prefs/segregated_pref_store_unittest.cc
@@ -381,15 +381,15 @@ const base::Value* value = nullptr; // Check that a selected preference is returned. ASSERT_TRUE(values->Get(kSelectedPref, &value)); - EXPECT_TRUE(base::Value(kValue1).Equals(value)); + EXPECT_EQ(base::Value(kValue1), *value); // Check that a a default preference is returned. ASSERT_TRUE(values->Get(kUnselectedPref, &value)); - EXPECT_TRUE(base::Value(kValue2).Equals(value)); + EXPECT_EQ(base::Value(kValue2), *value); // Check that the selected preference is preferred. ASSERT_TRUE(values->Get(kSharedPref, &value)); - EXPECT_TRUE(base::Value(kValue1).Equals(value)); + EXPECT_EQ(base::Value(kValue1), *value); } INSTANTIATE_TEST_SUITE_P(
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc index eca58f84..5936a766 100644 --- a/components/printing/renderer/print_render_frame_helper.cc +++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -2312,25 +2312,26 @@ return false; } - // TODO(dhoss): Replace deprecated base::DictionaryValue::Get<Type>() calls - if (!job_settings->GetInteger(kPreviewUIID, - &settings->params->preview_ui_id)) { + absl::optional<int> preview_ui_id = job_settings->FindIntKey(kPreviewUIID); + if (!preview_ui_id) { NOTREACHED(); print_preview_context_.set_error(PREVIEW_ERROR_BAD_SETTING); return false; } + settings->params->preview_ui_id = *preview_ui_id; // Validate expected print preview settings. absl::optional<bool> is_first_request = job_settings->FindBoolKey(kIsFirstRequest); - if (!job_settings->GetInteger(kPreviewRequestID, - &settings->params->preview_request_id) || - !is_first_request.has_value()) { + absl::optional<int> preview_request_id = + job_settings->FindIntKey(kPreviewRequestID); + if (!preview_request_id.has_value() || !is_first_request.has_value()) { NOTREACHED(); print_preview_context_.set_error(PREVIEW_ERROR_BAD_SETTING); return false; } settings->params->is_first_request = is_first_request.value(); + settings->params->preview_request_id = preview_request_id.value(); settings->params->print_to_pdf = IsPrintToPdfRequested(*job_settings); UpdateFrameMarginsCssInfo(*job_settings);
diff --git a/components/privacy_sandbox/privacy_sandbox_settings.cc b/components/privacy_sandbox/privacy_sandbox_settings.cc index 449eb05..cdb6e35 100644 --- a/components/privacy_sandbox/privacy_sandbox_settings.cc +++ b/components/privacy_sandbox/privacy_sandbox_settings.cc
@@ -276,10 +276,14 @@ void PrivacySandboxSettings::SetPrivacySandboxEnabled(bool enabled) { pref_service_->SetBoolean(prefs::kPrivacySandboxManuallyControlled, true); - // Simply apply the decision to both versions of the preference. The correct - // preference will be consulted when the value is read. - pref_service_->SetBoolean(prefs::kPrivacySandboxApisEnabled, enabled); - pref_service_->SetBoolean(prefs::kPrivacySandboxApisEnabledV2, enabled); + // Only apply the decision to the appropriate preference. Confirmation logic + // DCHECKS that the user has not been able to enable the V2 preference + // without seeing a dialog. + if (base::FeatureList::IsEnabled(privacy_sandbox::kPrivacySandboxSettings3)) { + pref_service_->SetBoolean(prefs::kPrivacySandboxApisEnabledV2, enabled); + } else { + pref_service_->SetBoolean(prefs::kPrivacySandboxApisEnabled, enabled); + } } void PrivacySandboxSettings::OnCookiesCleared() {
diff --git a/components/remote_cocoa/app_shim/mouse_capture.h b/components/remote_cocoa/app_shim/mouse_capture.h index 426404d3..59bdc58 100644 --- a/components/remote_cocoa/app_shim/mouse_capture.h +++ b/components/remote_cocoa/app_shim/mouse_capture.h
@@ -9,7 +9,11 @@ #include "components/remote_cocoa/app_shim/remote_cocoa_app_shim_export.h" +#if defined(__OBJC__) @class NSWindow; +#else +class NSWindow; +#endif namespace remote_cocoa {
diff --git a/components/remote_cocoa/app_shim/mouse_capture_delegate.h b/components/remote_cocoa/app_shim/mouse_capture_delegate.h index d85570b..9bc498b 100644 --- a/components/remote_cocoa/app_shim/mouse_capture_delegate.h +++ b/components/remote_cocoa/app_shim/mouse_capture_delegate.h
@@ -5,14 +5,21 @@ #ifndef COMPONENTS_REMOTE_COCOA_APP_SHIM_MOUSE_CAPTURE_DELEGATE_H_ #define COMPONENTS_REMOTE_COCOA_APP_SHIM_MOUSE_CAPTURE_DELEGATE_H_ +#if defined(__OBJC__) @class NSEvent; @class NSWindow; +#else +class NSEvent; +class NSWindow; +#endif namespace remote_cocoa { // Delegate for receiving captured events from a CocoaMouseCapture. class CocoaMouseCaptureDelegate { public: + virtual ~CocoaMouseCaptureDelegate() = default; + // Called when an event has been captured. This may be an event local to the // application, or a global event (sent to another application). If it is a // local event, regular event handling will be suppressed.
diff --git a/components/safe_browsing/content/browser/safe_browsing_blocking_page.cc b/components/safe_browsing/content/browser/safe_browsing_blocking_page.cc index 124f0e7..1d4c5f0 100644 --- a/components/safe_browsing/content/browser/safe_browsing_blocking_page.cc +++ b/components/safe_browsing/content/browser/safe_browsing_blocking_page.cc
@@ -37,29 +37,6 @@ namespace safe_browsing { -namespace { - -SafeBrowsingMetricsCollector::EventType GetEventTypeFromThreatSource( - ThreatSource threat_source) { - switch (threat_source) { - case ThreatSource::LOCAL_PVER4: - case ThreatSource::REMOTE: - return SafeBrowsingMetricsCollector::EventType:: - DATABASE_INTERSTITIAL_BYPASS; - case ThreatSource::CLIENT_SIDE_DETECTION: - return SafeBrowsingMetricsCollector::EventType::CSD_INTERSTITIAL_BYPASS; - case ThreatSource::REAL_TIME_CHECK: - return SafeBrowsingMetricsCollector::EventType:: - REAL_TIME_INTERSTITIAL_BYPASS; - default: - NOTREACHED() << "Unexpected threat source."; - return SafeBrowsingMetricsCollector::EventType:: - DATABASE_INTERSTITIAL_BYPASS; - } -} - -} // namespace - // static const security_interstitials::SecurityInterstitialPage::TypeID SafeBrowsingBlockingPage::kTypeForTesting = @@ -150,8 +127,7 @@ OnDontProceedDone(); } else { if (metrics_collector_) { - metrics_collector_->AddSafeBrowsingEventToPref( - GetEventTypeFromThreatSource(threat_source_)); + metrics_collector_->AddBypassEventToPref(threat_source_); } } BaseBlockingPage::OnInterstitialClosing();
diff --git a/components/safe_browsing/core/browser/BUILD.gn b/components/safe_browsing/core/browser/BUILD.gn index 9ee8f36f6..ca0491d 100644 --- a/components/safe_browsing/core/browser/BUILD.gn +++ b/components/safe_browsing/core/browser/BUILD.gn
@@ -153,6 +153,7 @@ "//base", "//components/keyed_service/core", "//components/prefs", + "//components/safe_browsing/core/browser/db:hit_report", "//components/safe_browsing/core/common:safe_browsing_prefs", ] }
diff --git a/components/safe_browsing/core/browser/safe_browsing_metrics_collector.cc b/components/safe_browsing/core/browser/safe_browsing_metrics_collector.cc index 51bda9c..c0612368 100644 --- a/components/safe_browsing/core/browser/safe_browsing_metrics_collector.cc +++ b/components/safe_browsing/core/browser/safe_browsing_metrics_collector.cc
@@ -11,6 +11,7 @@ #include "base/time/time.h" #include "components/prefs/pref_service.h" #include "components/prefs/scoped_user_pref_update.h" +#include "components/safe_browsing/core/browser/db/hit_report.h" #include "components/safe_browsing/core/common/safe_browsing_prefs.h" namespace { @@ -185,6 +186,27 @@ AddSafeBrowsingEventAndUserStateToPref(GetUserState(), event_type); } +void SafeBrowsingMetricsCollector::AddBypassEventToPref( + ThreatSource threat_source) { + EventType event; + switch (threat_source) { + case ThreatSource::LOCAL_PVER4: + case ThreatSource::REMOTE: + event = EventType::DATABASE_INTERSTITIAL_BYPASS; + break; + case ThreatSource::CLIENT_SIDE_DETECTION: + event = EventType::CSD_INTERSTITIAL_BYPASS; + break; + case ThreatSource::REAL_TIME_CHECK: + event = EventType::REAL_TIME_INTERSTITIAL_BYPASS; + break; + default: + NOTREACHED() << "Unexpected threat source."; + event = EventType::DATABASE_INTERSTITIAL_BYPASS; + } + AddSafeBrowsingEventToPref(event); +} + absl::optional<base::Time> SafeBrowsingMetricsCollector::GetLatestEventTimestamp(EventType event_type) { return GetLatestEventTimestamp(base::BindRepeating(
diff --git a/components/safe_browsing/core/browser/safe_browsing_metrics_collector.h b/components/safe_browsing/core/browser/safe_browsing_metrics_collector.h index c35e481b..02bf49d 100644 --- a/components/safe_browsing/core/browser/safe_browsing_metrics_collector.h +++ b/components/safe_browsing/core/browser/safe_browsing_metrics_collector.h
@@ -11,6 +11,7 @@ #include "base/timer/timer.h" #include "components/keyed_service/core/keyed_service.h" #include "components/prefs/pref_change_registrar.h" +#include "components/safe_browsing/core/browser/db/hit_report.h" #include "third_party/abseil-cpp/absl/types/optional.h" class PrefService; @@ -115,6 +116,10 @@ // Adds |event_type| and the current timestamp to pref. void AddSafeBrowsingEventToPref(EventType event_type); + // Uses |threat_source| to choose which EventType should be passed into + // AddSafeBrowsingEventToPref + void AddBypassEventToPref(ThreatSource threat_source); + // Gets the latest event timestamp of the |event_type|. Returns nullopt if // the |event_type| didn't happen in the past. absl::optional<base::Time> GetLatestEventTimestamp(EventType event_type);
diff --git a/components/search_engines/default_search_policy_handler_unittest.cc b/components/search_engines/default_search_policy_handler_unittest.cc index ccc583c..a091591 100644 --- a/components/search_engines/default_search_policy_handler_unittest.cc +++ b/components/search_engines/default_search_policy_handler_unittest.cc
@@ -219,11 +219,11 @@ EXPECT_TRUE( dictionary->GetList(DefaultSearchManager::kInputEncodings, &list_value)); - EXPECT_TRUE(encodings.Equals(list_value)); + EXPECT_EQ(encodings, *list_value); EXPECT_TRUE( dictionary->GetList(DefaultSearchManager::kAlternateURLs, &list_value)); - EXPECT_TRUE(default_alternate_urls_.Equals(list_value)); + EXPECT_EQ(default_alternate_urls_, *list_value); EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kImageURL, &value)); EXPECT_EQ(kImageURL, value); @@ -316,10 +316,10 @@ EXPECT_EQ(std::string(), value); EXPECT_TRUE( dictionary->GetList(DefaultSearchManager::kInputEncodings, &list_value)); - EXPECT_TRUE(base::ListValue().Equals(list_value)); + EXPECT_EQ(base::ListValue(), *list_value); EXPECT_TRUE( dictionary->GetList(DefaultSearchManager::kAlternateURLs, &list_value)); - EXPECT_TRUE(base::ListValue().Equals(list_value)); + EXPECT_EQ(base::ListValue(), *list_value); EXPECT_TRUE(dictionary->GetString(DefaultSearchManager::kImageURL, &value)); EXPECT_EQ(std::string(), value); EXPECT_TRUE(
diff --git a/components/segmentation_platform/internal/BUILD.gn b/components/segmentation_platform/internal/BUILD.gn index 430313df..b845fa2a 100644 --- a/components/segmentation_platform/internal/BUILD.gn +++ b/components/segmentation_platform/internal/BUILD.gn
@@ -40,10 +40,16 @@ "execution/feature_aggregator.h", "execution/feature_aggregator_impl.cc", "execution/feature_aggregator_impl.h", + "execution/feature_list_query_processor.cc", + "execution/feature_list_query_processor.h", + "execution/feature_processor_state.cc", + "execution/feature_processor_state.h", "execution/model_execution_manager.h", "execution/model_execution_manager_factory.cc", "execution/model_execution_manager_factory.h", "execution/model_execution_status.h", + "execution/uma_feature_processor.cc", + "execution/uma_feature_processor.h", "platform_options.cc", "platform_options.h", "scheduler/model_execution_scheduler.h", @@ -138,6 +144,9 @@ "dummy_segmentation_platform_service_unittest.cc", "execution/dummy_model_execution_manager_unittest.cc", "execution/feature_aggregator_impl_unittest.cc", + "execution/feature_list_query_processor_unittest.cc", + "execution/mock_feature_aggregator.cc", + "execution/mock_feature_aggregator.h", "execution/model_execution_manager_factory_unittest.cc", "scheduler/model_execution_scheduler_unittest.cc", "segmentation_platform_service_impl_unittest.cc",
diff --git a/components/segmentation_platform/internal/execution/feature_list_query_processor.cc b/components/segmentation_platform/internal/execution/feature_list_query_processor.cc new file mode 100644 index 0000000..5c4735c3 --- /dev/null +++ b/components/segmentation_platform/internal/execution/feature_list_query_processor.cc
@@ -0,0 +1,78 @@ +// Copyright 2022 The Chromium 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/segmentation_platform/internal/execution/feature_list_query_processor.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/time/clock.h" +#include "components/segmentation_platform/internal/database/metadata_utils.h" +#include "components/segmentation_platform/internal/execution/feature_processor_state.h" +#include "components/segmentation_platform/internal/execution/uma_feature_processor.h" +#include "components/segmentation_platform/internal/proto/model_metadata.pb.h" +#include "components/segmentation_platform/internal/stats.h" + +namespace segmentation_platform { + +FeatureListQueryProcessor::FeatureListQueryProcessor( + SignalDatabase* signal_database, + std::unique_ptr<FeatureAggregator> feature_aggregator) + : uma_feature_processor_(signal_database, std::move(feature_aggregator)) {} + +FeatureListQueryProcessor::~FeatureListQueryProcessor() = default; + +void FeatureListQueryProcessor::ProcessFeatureList( + const proto::SegmentationModelMetadata& model_metadata, + OptimizationTarget segment_id, + base::Time prediction_time, + FeatureProcessorCallback callback) { + // The total bucket duration is defined by product of the bucket_duration + // value and the length of related time_unit field, e.g. 28 * length(DAY). + base::TimeDelta time_unit_len = metadata_utils::GetTimeUnit(model_metadata); + base::TimeDelta bucket_duration = + model_metadata.bucket_duration() * time_unit_len; + + // Grab the metadata for all the features, which will be processed one at a + // time, before executing the model. + auto input_features = std::make_unique<std::deque<proto::InputFeature>>(); + for (int i = 0; i < model_metadata.features_size(); ++i) { + proto::InputFeature input_feature; + input_feature.mutable_uma_feature()->CopyFrom(model_metadata.features(i)); + input_features->emplace_back(input_feature); + } + for (int i = 0; i < model_metadata.input_features_size(); ++i) + input_features->emplace_back(model_metadata.input_features(i)); + + // Capture all the relevant metadata information into a FeatureProcessorState. + auto feature_processor_state = std::make_unique<FeatureProcessorState>( + prediction_time, bucket_duration, segment_id, std::move(input_features), + std::move(callback)); + + ProcessNextInputFeature(std::move(feature_processor_state)); +} + +void FeatureListQueryProcessor::ProcessNextInputFeature( + std::unique_ptr<FeatureProcessorState> feature_processor_state) { + // Finished processing all input features. + if (feature_processor_state->IsFeatureListEmpty()) { + feature_processor_state->RunCallback(); + return; + } + + // Get next input feature to process. + proto::InputFeature input_feature = + feature_processor_state->PopNextInputFeature(); + + if (input_feature.has_uma_feature()) { + // Process all the features in-order, starting with the first feature. + uma_feature_processor_.ProcessUmaFeature( + input_feature.uma_feature(), std::move(feature_processor_state), + base::BindOnce(&FeatureListQueryProcessor::ProcessNextInputFeature, + weak_ptr_factory_.GetWeakPtr())); + } +} + +} // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/execution/feature_list_query_processor.h b/components/segmentation_platform/internal/execution/feature_list_query_processor.h new file mode 100644 index 0000000..08dec612 --- /dev/null +++ b/components/segmentation_platform/internal/execution/feature_list_query_processor.h
@@ -0,0 +1,67 @@ +// Copyright 2022 The Chromium 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_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_LIST_QUERY_PROCESSOR_H_ +#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_LIST_QUERY_PROCESSOR_H_ + +#include <deque> +#include <vector> + +#include "base/memory/weak_ptr.h" +#include "components/optimization_guide/proto/models.pb.h" +#include "components/segmentation_platform/internal/execution/model_execution_manager_impl.h" +#include "components/segmentation_platform/internal/execution/uma_feature_processor.h" +#include "components/segmentation_platform/internal/proto/model_metadata.pb.h" + +namespace segmentation_platform { +class FeatureAggregator; +class FeatureProcessorState; +class SignalDatabase; + +// FeatureListQueryProcessor takes a segmentation model's metadata, processes +// each feature in the metadata's feature list in order and computes an input +// tensor to use when executing the ML model. +class FeatureListQueryProcessor { + public: + FeatureListQueryProcessor( + SignalDatabase* signal_database, + std::unique_ptr<FeatureAggregator> feature_aggregator); + virtual ~FeatureListQueryProcessor(); + + // Disallow copy/assign. + FeatureListQueryProcessor(const FeatureListQueryProcessor&) = delete; + FeatureListQueryProcessor& operator=(const FeatureListQueryProcessor&) = + delete; + + using FeatureProcessorCallback = + base::OnceCallback<void(bool, const std::vector<float>&)>; + + // Given a model's metadata, processes the feature list from the metadata and + // computes the input tensor for the ML model. Result is returned through a + // callback. + // |segment_id| is only used for recording performance metrics. This class + // does not need to know about the segment itself. |prediction_time| is the + // time at which we predict the model execution should happen. + void ProcessFeatureList( + const proto::SegmentationModelMetadata& model_metadata, + OptimizationTarget segment_id, + base::Time prediction_time, + FeatureProcessorCallback callback); + + private: + // Called by ProcessFeatureList to process the next input feature in the list. + // It then delegates the processing to the correct feature processor class + // until the feature list is empty. + void ProcessNextInputFeature( + std::unique_ptr<FeatureProcessorState> feature_processor_state); + + // Feature processor for uma type of input features. + UmaFeatureProcessor uma_feature_processor_; + + base::WeakPtrFactory<FeatureListQueryProcessor> weak_ptr_factory_{this}; +}; + +} // namespace segmentation_platform + +#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_LIST_QUERY_PROCESSOR_H_
diff --git a/components/segmentation_platform/internal/execution/feature_list_query_processor_unittest.cc b/components/segmentation_platform/internal/execution/feature_list_query_processor_unittest.cc new file mode 100644 index 0000000..18539ce --- /dev/null +++ b/components/segmentation_platform/internal/execution/feature_list_query_processor_unittest.cc
@@ -0,0 +1,418 @@ +// Copyright 2022 The Chromium 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/segmentation_platform/internal/execution/feature_list_query_processor.h" + +#include <memory> + +#include "base/bind.h" +#include "base/metrics/metrics_hashes.h" +#include "base/run_loop.h" +#include "base/test/gmock_callback_support.h" +#include "base/test/simple_test_clock.h" +#include "base/test/task_environment.h" +#include "components/segmentation_platform/internal/database/mock_signal_database.h" +#include "components/segmentation_platform/internal/execution/mock_feature_aggregator.h" +#include "testing/gtest/include/gtest/gtest.h" + +using base::test::RunOnceCallback; +using SignalDatabaseSample = segmentation_platform::SignalDatabase::Sample; +using testing::_; +using testing::Return; +using testing::SetArgReferee; + +namespace segmentation_platform { + +namespace { +constexpr base::TimeDelta kOneSecond = base::Seconds(1); +constexpr base::TimeDelta kTwoSeconds = base::Seconds(2); +} // namespace + +class FeatureListQueryProcessorTest : public testing::Test { + public: + FeatureListQueryProcessorTest() = default; + ~FeatureListQueryProcessorTest() override = default; + + void SetUp() override { + signal_database_ = std::make_unique<MockSignalDatabase>(); + clock_.SetNow(base::Time::Now()); + segment_id_ = OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; + } + + void TearDown() override { + feature_list_query_processor_.reset(); + // Allow for the background class to be destroyed. + RunUntilIdle(); + } + + void RunUntilIdle() { task_environment_.RunUntilIdle(); } + + void CreateFeatureListQueryProcessor() { + auto feature_aggregator = std::make_unique<MockFeatureAggregator>(); + feature_aggregator_ = feature_aggregator.get(); + feature_list_query_processor_ = std::make_unique<FeatureListQueryProcessor>( + signal_database_.get(), std::move(feature_aggregator)); + } + + void SetBucketDuration(uint64_t bucket_duration, proto::TimeUnit time_unit) { + model_metadata.set_bucket_duration(bucket_duration); + model_metadata.set_time_unit(time_unit); + } + + base::Time StartTime(base::TimeDelta bucket_duration, int64_t bucket_count) { + return clock_.Now() - bucket_duration * bucket_count; + } + + void AddUmaFeature(proto::SignalType signal_type, + const std::string& name, + uint64_t bucket_count, + uint64_t tensor_length, + proto::Aggregation aggregation, + const std::vector<int32_t>& accepted_enum_ids) { + auto* input_feature = model_metadata.add_input_features(); + proto::UMAFeature* uma_feature = input_feature->mutable_uma_feature(); + uma_feature->set_type(signal_type); + uma_feature->set_name(name); + uma_feature->set_name_hash(base::HashMetricName(name)); + uma_feature->set_bucket_count(bucket_count); + uma_feature->set_tensor_length(tensor_length); + uma_feature->set_aggregation(aggregation); + + for (int32_t accepted_enum_id : accepted_enum_ids) + uma_feature->add_enum_ids(accepted_enum_id); + } + + void ProcessFeatureList(bool expected_error, + const std::vector<float>& expected_input_tensor) { + base::RunLoop loop; + feature_list_query_processor_->ProcessFeatureList( + model_metadata, segment_id_, clock_.Now(), + base::BindOnce( + &FeatureListQueryProcessorTest::OnProcessingFinishedCallback, + base::Unretained(this), loop.QuitClosure(), expected_error, + expected_input_tensor)); + loop.Run(); + } + + void OnProcessingFinishedCallback( + base::RepeatingClosure closure, + bool expected_error, + const std::vector<float>& expected_input_tensor, + bool error, + const std::vector<float>& input_tensor) { + EXPECT_EQ(expected_error, error); + EXPECT_EQ(expected_input_tensor, input_tensor); + std::move(closure).Run(); + } + + base::SimpleTestClock clock_; + base::test::TaskEnvironment task_environment_; + OptimizationTarget segment_id_; + proto::SegmentationModelMetadata model_metadata; + std::unique_ptr<MockSignalDatabase> signal_database_; + raw_ptr<MockFeatureAggregator> feature_aggregator_; + + std::unique_ptr<FeatureListQueryProcessor> feature_list_query_processor_; +}; + +TEST_F(FeatureListQueryProcessorTest, InvalidMetadata) { + CreateFeatureListQueryProcessor(); + + // Initialize with required metadata. + SetBucketDuration(3, proto::TimeUnit::HOUR); + + // Set up a single invalid feature. + std::string invalid_uma_feature = "invalid_uma_feature"; + AddUmaFeature(proto::SignalType::UNKNOWN_SIGNAL_TYPE, invalid_uma_feature, 2, + 1, proto::Aggregation::COUNT, {}); + + // The next step should be to run the feature processor. + ProcessFeatureList(true, std::vector<float>{}); +} + +TEST_F(FeatureListQueryProcessorTest, SingleUserAction) { + CreateFeatureListQueryProcessor(); + + // Initialize with required metadata. + SetBucketDuration(3, proto::TimeUnit::HOUR); + base::TimeDelta bucket_duration = base::Hours(3); + + // Set up a single user action feature. + std::string user_action_name_1 = "some_action_1"; + AddUmaFeature(proto::SignalType::USER_ACTION, user_action_name_1, 2, 1, + proto::Aggregation::COUNT, {}); + + // When the particular user action is looked up with the correct start time, + // end time, and aggregation type, return 3 samples. + std::vector<SignalDatabaseSample> samples{ + {clock_.Now(), 0}, + {clock_.Now(), 0}, + {clock_.Now(), 0}, + }; + EXPECT_CALL(*signal_database_, + GetSamples(proto::SignalType::USER_ACTION, + base::HashMetricName(user_action_name_1), + StartTime(bucket_duration, 2), clock_.Now(), _)) + .WillOnce(RunOnceCallback<4>(samples)); + + // After retrieving the samples, they should be processed and aggregated. + EXPECT_CALL(*feature_aggregator_, + Process(proto::SignalType::USER_ACTION, proto::Aggregation::COUNT, + 2, clock_.Now(), bucket_duration, samples)) + .WillOnce(Return(std::vector<float>{3})); + + // The next step should be to run the feature processor. + ProcessFeatureList(false, std::vector<float>{3}); +} + +TEST_F(FeatureListQueryProcessorTest, MultipleUmaFeatures) { + CreateFeatureListQueryProcessor(); + + // Initialize with required metadata. + SetBucketDuration(3, proto::TimeUnit::HOUR); + base::TimeDelta bucket_duration = base::Hours(3); + + // Set up 3 metadata feature, one of each signal type. + std::string user_action_name = "some_user_action"; + AddUmaFeature(proto::SignalType::USER_ACTION, user_action_name, 2, 1, + proto::Aggregation::COUNT, {}); + std::string histogram_value_name = "some_histogram_value"; + AddUmaFeature(proto::SignalType::HISTOGRAM_VALUE, histogram_value_name, 3, 1, + proto::Aggregation::SUM, {}); + std::string histogram_enum_name = "some_histogram_enum"; + AddUmaFeature(proto::SignalType::HISTOGRAM_ENUM, histogram_enum_name, 4, 1, + proto::Aggregation::COUNT, {}); + + // First uma feature should be the user action. + std::vector<SignalDatabaseSample> user_action_samples{ + {clock_.Now(), 0}, + {clock_.Now(), 0}, + {clock_.Now(), 0}, + }; + EXPECT_CALL(*signal_database_, + GetSamples(proto::SignalType::USER_ACTION, + base::HashMetricName(user_action_name), + StartTime(bucket_duration, 2), clock_.Now(), _)) + .WillOnce(RunOnceCallback<4>(user_action_samples)); + EXPECT_CALL(*feature_aggregator_, + Process(proto::SignalType::USER_ACTION, proto::Aggregation::COUNT, + 2, clock_.Now(), bucket_duration, user_action_samples)) + .WillOnce(Return(std::vector<float>{3})); + + // Second uma feature should be the value histogram. + std::vector<SignalDatabaseSample> histogram_value_samples{ + {clock_.Now(), 1}, + {clock_.Now(), 2}, + {clock_.Now(), 3}, + }; + EXPECT_CALL(*signal_database_, + GetSamples(proto::SignalType::HISTOGRAM_VALUE, + base::HashMetricName(histogram_value_name), + StartTime(bucket_duration, 3), clock_.Now(), _)) + .WillOnce(RunOnceCallback<4>(histogram_value_samples)); + EXPECT_CALL( + *feature_aggregator_, + Process(proto::SignalType::HISTOGRAM_VALUE, proto::Aggregation::SUM, 3, + clock_.Now(), bucket_duration, histogram_value_samples)) + .WillOnce(Return(std::vector<float>{6})); + + // Third uma feature should be the enum histogram. + std::vector<SignalDatabaseSample> histogram_enum_samples{ + {clock_.Now(), 1}, + {clock_.Now(), 2}, + {clock_.Now(), 3}, + {clock_.Now(), 4}, + }; + EXPECT_CALL(*signal_database_, + GetSamples(proto::SignalType::HISTOGRAM_ENUM, + base::HashMetricName(histogram_enum_name), + StartTime(bucket_duration, 4), clock_.Now(), _)) + .WillOnce(RunOnceCallback<4>(histogram_enum_samples)); + EXPECT_CALL( + *feature_aggregator_, + Process(proto::SignalType::HISTOGRAM_ENUM, proto::Aggregation::COUNT, 4, + clock_.Now(), bucket_duration, histogram_enum_samples)) + .WillOnce(Return(std::vector<float>{4})); + + // The input tensor should contain all three values: 3, 6, and 4. + ProcessFeatureList(false, std::vector<float>{3, 6, 4}); +} + +TEST_F(FeatureListQueryProcessorTest, SkipCollectionOnlyUmaFeatures) { + CreateFeatureListQueryProcessor(); + + // Initialize with required metadata. + SetBucketDuration(3, proto::TimeUnit::HOUR); + base::TimeDelta bucket_duration = base::Hours(3); + + // Set up 3 metadata feature, one of each signal type. + std::string collected_user_action = "some_user_action"; + AddUmaFeature(proto::SignalType::USER_ACTION, collected_user_action, 1, 1, + proto::Aggregation::COUNT, {}); + std::string no_collection_user_action = "no_collection_user_action"; + AddUmaFeature(proto::SignalType::USER_ACTION, no_collection_user_action, 0, 0, + proto::Aggregation::SUM, {}); + std::string no_collection_histogram_value = "no_collection_histogram_value"; + AddUmaFeature(proto::SignalType::HISTOGRAM_VALUE, + no_collection_histogram_value, 0, 0, proto::Aggregation::SUM, + {}); + std::string no_collection_histogram_enum = "no_collection_histogram_enum"; + AddUmaFeature(proto::SignalType::HISTOGRAM_ENUM, no_collection_histogram_enum, + 0, 0, proto::Aggregation::SUM, {}); + std::string collected_histogram_value = "collected_histogram_value"; + AddUmaFeature(proto::SignalType::HISTOGRAM_VALUE, collected_histogram_value, + 1, 1, proto::Aggregation::SUM, {}); + + // The first uma feature in use should be the very first uma feature. + std::vector<SignalDatabaseSample> user_action_samples{ + {clock_.Now(), 0}, + {clock_.Now(), 0}, + {clock_.Now(), 0}, + }; + EXPECT_CALL(*signal_database_, + GetSamples(proto::SignalType::USER_ACTION, + base::HashMetricName(collected_user_action), + StartTime(bucket_duration, 1), clock_.Now(), _)) + .WillOnce(RunOnceCallback<4>(user_action_samples)); + EXPECT_CALL(*feature_aggregator_, + Process(proto::SignalType::USER_ACTION, proto::Aggregation::COUNT, + 1, clock_.Now(), bucket_duration, user_action_samples)) + .WillOnce(Return(std::vector<float>{3})); + + // The three uma features in the middle should all be ignored, so the next one + // should be the last uma feature. + std::vector<SignalDatabaseSample> histogram_value_samples{ + {clock_.Now(), 1}, + {clock_.Now(), 2}, + {clock_.Now(), 3}, + }; + EXPECT_CALL(*signal_database_, + GetSamples(proto::SignalType::HISTOGRAM_VALUE, + base::HashMetricName(collected_histogram_value), + StartTime(bucket_duration, 1), clock_.Now(), _)) + .WillOnce(RunOnceCallback<4>(histogram_value_samples)); + EXPECT_CALL( + *feature_aggregator_, + Process(proto::SignalType::HISTOGRAM_VALUE, proto::Aggregation::SUM, 1, + clock_.Now(), bucket_duration, histogram_value_samples)) + .WillOnce(Return(std::vector<float>{6})); + + // The input tensor should contain only the first and last uma feature. + ProcessFeatureList(false, std::vector<float>{3, 6}); +} + +TEST_F(FeatureListQueryProcessorTest, FilteredEnumSamples) { + CreateFeatureListQueryProcessor(); + + // Initialize with required metadata. + SetBucketDuration(3, proto::TimeUnit::HOUR); + base::TimeDelta bucket_duration = base::Hours(3); + + // Set up a single enum histogram feature. + std::string histogram_enum_name = "some_histogram_enum"; + std::vector<int32_t> accepted_enum_ids = {2, 4}; + AddUmaFeature(proto::SignalType::HISTOGRAM_ENUM, histogram_enum_name, 4, 1, + proto::Aggregation::COUNT, accepted_enum_ids); + + // When the particular enum histogram is looked up with the correct start + // time, end time, and aggregation type, return all 5 samples. + std::vector<SignalDatabaseSample> histogram_enum_samples{ + {clock_.Now(), 1}, {clock_.Now(), 2}, {clock_.Now(), 3}, + {clock_.Now(), 4}, {clock_.Now(), 5}, + }; + EXPECT_CALL(*signal_database_, + GetSamples(proto::SignalType::HISTOGRAM_ENUM, + base::HashMetricName(histogram_enum_name), + StartTime(bucket_duration, 4), clock_.Now(), _)) + .WillOnce(RunOnceCallback<4>(histogram_enum_samples)); + // The executor must first filter the enum samples. + std::vector<SignalDatabaseSample> filtered_enum_samples{ + {clock_.Now(), 2}, + {clock_.Now(), 4}, + }; + EXPECT_CALL(*feature_aggregator_, + FilterEnumSamples(accepted_enum_ids, histogram_enum_samples)) + .WillOnce(SetArgReferee<1>(filtered_enum_samples)); + // Only filtered_enum_samples should be processed. + EXPECT_CALL( + *feature_aggregator_, + Process(proto::SignalType::HISTOGRAM_ENUM, proto::Aggregation::COUNT, 4, + clock_.Now(), bucket_duration, filtered_enum_samples)) + .WillOnce(Return(std::vector<float>{2})); + + // The input tensor should contain a single value. + ProcessFeatureList(false, std::vector<float>{2}); +} + +TEST_F(FeatureListQueryProcessorTest, MultipleUmaFeaturesWithMultipleBuckets) { + CreateFeatureListQueryProcessor(); + + // Initialize with required metadata. + SetBucketDuration(3, proto::TimeUnit::HOUR); + base::TimeDelta bucket_duration = base::Hours(3); + + // Set up metadata uma features where bucket_count is not equal to 1. + std::string user_action_name = "some_user_action"; + // 3 buckets + AddUmaFeature(proto::SignalType::USER_ACTION, user_action_name, 3, 3, + proto::Aggregation::BUCKETED_COUNT, {}); + std::string histogram_value_name = "some_histogram_value"; + // 4 buckets + AddUmaFeature(proto::SignalType::HISTOGRAM_VALUE, histogram_value_name, 4, 4, + proto::Aggregation::BUCKETED_COUNT_BOOLEAN, {}); + + // First uma feature should be the user action. The timestamp is set to three + // different buckets. + std::vector<SignalDatabaseSample> user_action_samples{ + {clock_.Now(), 0}, + {clock_.Now() - kOneSecond, 0}, + {clock_.Now() - bucket_duration, 0}, + {clock_.Now() - bucket_duration - kOneSecond, 0}, + {clock_.Now() - bucket_duration - kTwoSeconds, 0}, + {clock_.Now() - bucket_duration * 2, 0}, + {clock_.Now() - bucket_duration * 2 - kOneSecond, 0}, + {clock_.Now() - bucket_duration * 2 - kTwoSeconds, 0}, + }; + EXPECT_CALL(*signal_database_, + GetSamples(proto::SignalType::USER_ACTION, + base::HashMetricName(user_action_name), + StartTime(bucket_duration, 3), clock_.Now(), _)) + .WillOnce(RunOnceCallback<4>(user_action_samples)); + EXPECT_CALL(*feature_aggregator_, + Process(proto::SignalType::USER_ACTION, + proto::Aggregation::BUCKETED_COUNT, 3, clock_.Now(), + bucket_duration, user_action_samples)) + .WillOnce(Return(std::vector<float>{1, 2, 3})); + + // Second uma feature should be the value histogram. The timestamp is set to + // four different buckets. + std::vector<SignalDatabaseSample> histogram_value_samples{ + {clock_.Now(), 1}, + {clock_.Now() - kOneSecond, 2}, + {clock_.Now() - bucket_duration, 3}, + {clock_.Now() - bucket_duration - kOneSecond, 4}, + {clock_.Now() - bucket_duration - kTwoSeconds, 5}, + {clock_.Now() - bucket_duration * 2, 6}, + {clock_.Now() - bucket_duration * 2 - kOneSecond, 7}, + {clock_.Now() - bucket_duration * 2 - kTwoSeconds, 8}, + {clock_.Now() - bucket_duration * 3, 9}, + {clock_.Now() - bucket_duration * 3 - kOneSecond, 10}, + {clock_.Now() - bucket_duration * 3 - kTwoSeconds, 11}, + }; + EXPECT_CALL(*signal_database_, + GetSamples(proto::SignalType::HISTOGRAM_VALUE, + base::HashMetricName(histogram_value_name), + StartTime(bucket_duration, 4), clock_.Now(), _)) + .WillOnce(RunOnceCallback<4>(histogram_value_samples)); + EXPECT_CALL(*feature_aggregator_, + Process(proto::SignalType::HISTOGRAM_VALUE, + proto::Aggregation::BUCKETED_COUNT_BOOLEAN, 4, + clock_.Now(), bucket_duration, histogram_value_samples)) + .WillOnce(Return(std::vector<float>{4, 5, 6, 7})); + + // The input tensor should contain all values flattened to a single vector. + ProcessFeatureList(false, std::vector<float>{1, 2, 3, 4, 5, 6, 7}); +} + +} // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/execution/feature_processor_state.cc b/components/segmentation_platform/internal/execution/feature_processor_state.cc new file mode 100644 index 0000000..72fa832 --- /dev/null +++ b/components/segmentation_platform/internal/execution/feature_processor_state.cc
@@ -0,0 +1,46 @@ +// Copyright 2022 The Chromium 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/segmentation_platform/internal/execution/feature_processor_state.h" + +namespace segmentation_platform { + +FeatureProcessorState::FeatureProcessorState( + base::Time prediction_time, + base::TimeDelta bucket_duration, + OptimizationTarget segment_id, + std::unique_ptr<std::deque<proto::InputFeature>> input_features, + FeatureListQueryProcessor::FeatureProcessorCallback callback) + : prediction_time_(prediction_time), + bucket_duration_(bucket_duration), + segment_id_(segment_id), + input_features_(std::move(input_features)), + callback_(std::move(callback)) {} + +FeatureProcessorState::~FeatureProcessorState() = default; + +void FeatureProcessorState::SetError() { + error_ = true; +} + +proto::InputFeature FeatureProcessorState::PopNextInputFeature() { + proto::InputFeature input_feature = std::move(input_features_->front()); + input_features_->pop_front(); + return input_feature; +} + +bool FeatureProcessorState::IsFeatureListEmpty() const { + return input_features_->empty(); +} + +void FeatureProcessorState::RunCallback() { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback_), error_, input_tensor_)); +} + +void FeatureProcessorState::AppendInputTensor(const std::vector<float>& data) { + input_tensor_.insert(input_tensor_.end(), data.begin(), data.end()); +} + +} // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/execution/feature_processor_state.h b/components/segmentation_platform/internal/execution/feature_processor_state.h new file mode 100644 index 0000000..76b6405 --- /dev/null +++ b/components/segmentation_platform/internal/execution/feature_processor_state.h
@@ -0,0 +1,72 @@ +// Copyright 2022 The Chromium 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_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_PROCESSOR_STATE_H_ +#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_PROCESSOR_STATE_H_ + +#include <deque> +#include <vector> + +#include "base/time/clock.h" +#include "components/optimization_guide/proto/models.pb.h" +#include "components/segmentation_platform/internal/execution/feature_list_query_processor.h" +#include "components/segmentation_platform/internal/proto/model_metadata.pb.h" + +namespace segmentation_platform { + +// FeatureProcessorState is responsible for storing all necessary state during +// the processing of a model's metadata. +class FeatureProcessorState { + public: + FeatureProcessorState( + base::Time prediction_time, + base::TimeDelta bucket_duration, + OptimizationTarget segment_id, + std::unique_ptr<std::deque<proto::InputFeature>> input_features, + FeatureListQueryProcessor::FeatureProcessorCallback callback); + virtual ~FeatureProcessorState(); + + // Disallow copy/assign. + FeatureProcessorState(const FeatureProcessorState&) = delete; + FeatureProcessorState& operator=(const FeatureProcessorState&) = delete; + + // Getters. + base::TimeDelta bucket_duration() const { return bucket_duration_; } + + base::Time prediction_time() const { return prediction_time_; } + + OptimizationTarget segment_id() const { return segment_id_; } + + // Returns and pops the next input feature in the feature list. + proto::InputFeature PopNextInputFeature(); + + // Sets an error to the current feature processor state. + void SetError(); + + // Returns whether the input feature list is empty. + bool IsFeatureListEmpty() const; + + // Run the callback stored in the current feature processor state. + void RunCallback(); + + // Update the input tensor vector. + void AppendInputTensor(const std::vector<float>& data); + + private: + const base::Time prediction_time_; + const base::TimeDelta bucket_duration_; + const OptimizationTarget segment_id_; + std::unique_ptr<std::deque<proto::InputFeature>> input_features_; + + // Feature processing results. + std::vector<float> input_tensor_; + bool error_{false}; + + // Callback to return feature processing results to model execution manager. + FeatureListQueryProcessor::FeatureProcessorCallback callback_; +}; + +} // namespace segmentation_platform + +#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_FEATURE_PROCESSOR_STATE_H_
diff --git a/components/segmentation_platform/internal/execution/mock_feature_aggregator.cc b/components/segmentation_platform/internal/execution/mock_feature_aggregator.cc new file mode 100644 index 0000000..1aa1ab8 --- /dev/null +++ b/components/segmentation_platform/internal/execution/mock_feature_aggregator.cc
@@ -0,0 +1,12 @@ +// Copyright 2022 The Chromium 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/segmentation_platform/internal/execution/mock_feature_aggregator.h" + +namespace segmentation_platform { + +MockFeatureAggregator::MockFeatureAggregator() = default; +MockFeatureAggregator::~MockFeatureAggregator() = default; + +} // namespace segmentation_platform \ No newline at end of file
diff --git a/components/segmentation_platform/internal/execution/mock_feature_aggregator.h b/components/segmentation_platform/internal/execution/mock_feature_aggregator.h new file mode 100644 index 0000000..29bb256 --- /dev/null +++ b/components/segmentation_platform/internal/execution/mock_feature_aggregator.h
@@ -0,0 +1,38 @@ +// Copyright 2022 The Chromium 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_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MOCK_FEATURE_AGGREGATOR_H_ +#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MOCK_FEATURE_AGGREGATOR_H_ + +#include <vector> + +#include "components/segmentation_platform/internal/execution/feature_aggregator.h" +#include "testing/gmock/include/gmock/gmock.h" + +namespace segmentation_platform { + +// Mock of feature aggregator class. Used for testing. +class MockFeatureAggregator : public FeatureAggregator { + public: + MockFeatureAggregator(); + ~MockFeatureAggregator() override; + MOCK_METHOD(std::vector<float>, + Process, + (proto::SignalType signal_type, + proto::Aggregation aggregation, + uint64_t bucket_count, + const base::Time& end_time, + const base::TimeDelta& bucket_duration, + const std::vector<SignalDatabase::Sample>& samples), + (const override)); + MOCK_METHOD(void, + FilterEnumSamples, + (const std::vector<int32_t>& accepted_enum_ids, + std::vector<SignalDatabase::Sample>& samples), + (const override)); +}; + +} // namespace segmentation_platform + +#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_MOCK_FEATURE_AGGREGATOR_H_ \ No newline at end of file
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc b/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc index da39398..6d75951c 100644 --- a/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc +++ b/components/segmentation_platform/internal/execution/model_execution_manager_impl.cc
@@ -22,6 +22,7 @@ #include "components/segmentation_platform/internal/database/metadata_utils.h" #include "components/segmentation_platform/internal/database/signal_database.h" #include "components/segmentation_platform/internal/execution/feature_aggregator.h" +#include "components/segmentation_platform/internal/execution/feature_list_query_processor.h" #include "components/segmentation_platform/internal/execution/model_execution_manager.h" #include "components/segmentation_platform/internal/execution/model_execution_status.h" #include "components/segmentation_platform/internal/execution/segmentation_model_handler.h" @@ -76,10 +77,7 @@ OptimizationTarget segment_id; raw_ptr<SegmentationModelHandler> model_handler = nullptr; ModelExecutionCallback callback; - base::TimeDelta bucket_duration; - std::deque<proto::InputFeature> input_features; std::vector<float> input_tensor; - base::Time end_time; base::Time total_execution_start_time; base::Time model_execution_start_time; }; @@ -98,21 +96,6 @@ perfetto::Track::FromPointer(&state)); } -struct ModelExecutionManagerImpl::FeatureState { - FeatureState() = default; - ~FeatureState() = default; - - // Disallow copy/assign. - FeatureState(const FeatureState&) = delete; - FeatureState& operator=(const FeatureState&) = delete; - - proto::SignalType signal_type; - proto::Aggregation aggregation; - absl::optional<std::vector<int32_t>> accepted_enum_ids; - uint64_t bucket_count; - uint64_t tensor_length; -}; - ModelExecutionManagerImpl::ModelExecutionManagerImpl( const base::flat_set<OptimizationTarget>& segment_ids, ModelHandlerCreator model_handler_creator, @@ -124,8 +107,9 @@ : clock_(clock), segment_database_(segment_database), signal_database_(signal_database), - feature_aggregator_(std::move(feature_aggregator)), model_updated_callback_(model_updated_callback) { + feature_list_query_processor_ = std::make_unique<FeatureListQueryProcessor>( + signal_database, std::move(feature_aggregator)); for (OptimizationTarget segment_id : segment_ids) { model_handlers_.emplace(std::make_pair( segment_id, @@ -178,148 +162,28 @@ return; } - // The total bucket duration is defined by product of the bucket_duration - // value and the length of related time_unit field, e.g. 28 * length(DAY). - const auto& model_metadata = segment_info->model_metadata(); - uint64_t bucket_duration = model_metadata.bucket_duration(); - base::TimeDelta time_unit_len = metadata_utils::GetTimeUnit(model_metadata); - state->bucket_duration = bucket_duration * time_unit_len; - - // Now that we have just fetched the metadata, set the end_time to be shared - // across all features, so we get a consistent picture. - state->end_time = clock_->Now(); - - // Grab the metadata for all the features, which will be processed one at a - // time, before executing the model. - for (int i = 0; i < model_metadata.features_size(); ++i) { - proto::InputFeature input_feature; - input_feature.mutable_uma_feature()->CopyFrom(model_metadata.features(i)); - state->input_features.emplace_back(input_feature); - } - for (int i = 0; i < model_metadata.input_features_size(); ++i) - state->input_features.emplace_back(model_metadata.input_features(i)); - - ProcessInputFeatures(std::move(state)); + OptimizationTarget segment_id = state->segment_id; + feature_list_query_processor_->ProcessFeatureList( + segment_info->model_metadata(), segment_id, clock_->Now(), + base::BindOnce( + &ModelExecutionManagerImpl::OnProcessingFeatureListComplete, + weak_ptr_factory_.GetWeakPtr(), std::move(state))); } -void ModelExecutionManagerImpl::ProcessInputFeatures( - std::unique_ptr<ExecutionState> state) { - if (state->input_features.empty()) { - ExecuteModel(std::move(state)); - } else { - if (state->input_features.front().has_uma_feature()) { - // Process all the features in-order, starting with the first feature. - proto::InputFeature input_feature; - input_feature = state->input_features.front(); - state->input_features.pop_front(); - ProcessNextUmaFeature(input_feature.uma_feature(), std::move(state)); - } - } -} - -void ModelExecutionManagerImpl::ProcessNextUmaFeature( - proto::UMAFeature feature, - std::unique_ptr<ExecutionState> state) { - ModelExecutionTraceEvent trace_event( - "ModelExecutionManagerImpl::ProcessNextUmaFeature", *state); - - // Skip collection-only features. - if (feature.bucket_count() == 0) { - ProcessInputFeatures(std::move(state)); - return; - } - - // Validate the proto::UMAFeature metadata. - if (metadata_utils::ValidateMetadataUmaFeature(feature) != - metadata_utils::ValidationResult::kValidationSuccess) { +void ModelExecutionManagerImpl::OnProcessingFeatureListComplete( + std::unique_ptr<ExecutionState> state, + bool error, + const std::vector<float>& input_tensor) { + if (error) { + // Validation error occurred on model's metadata. RunModelExecutionCallback(std::move(state), 0, ModelExecutionStatus::kInvalidMetadata); return; } + state->input_tensor.insert(state->input_tensor.end(), input_tensor.begin(), + input_tensor.end()); - // Capture all relevant metadata for the current proto::UMAFeature into the - // FeatureState. - auto feature_state = std::make_unique<FeatureState>(); - feature_state->signal_type = feature.type(); - feature_state->aggregation = feature.aggregation(); - feature_state->bucket_count = feature.bucket_count(); - feature_state->tensor_length = feature.tensor_length(); - - auto name_hash = feature.name_hash(); - - // Enum histograms can optionally only accept some of the enum values. - // While the proto::UMAFeature is available, capture a vector of the - // accepted enum values. An empty vector is ignored (all values are - // considered accepted). - if (feature_state->signal_type == proto::SignalType::HISTOGRAM_ENUM) { - std::vector<int32_t> accepted_enum_ids{}; - for (int i = 0; i < feature.enum_ids_size(); ++i) - accepted_enum_ids.emplace_back(feature.enum_ids(i)); - - feature_state->accepted_enum_ids = absl::make_optional(accepted_enum_ids); - } - - // Only fetch data that is relevant for the current proto::UMAFeature, since - // the FeatureAggregator assumes that only relevant data is given to it. - base::TimeDelta duration = - state->bucket_duration * feature_state->bucket_count; - base::Time start_time = state->end_time - duration; - - // Fetch the relevant samples for the current proto::UMAFeature. Once the - // result has come back, it will be processed and inserted into the - // ExecutorState::input_tensor and will then invoke - // ProcessInputFeatures(...) again to ensure we continue until all features - // have been processed. Note: All parameters from the ExecutorState need to - // be captured locally before invoking GetSamples, because the state is - // moved with the callback, and the order of the move and accessing the - // members while invoking GetSamples is not guaranteed. - auto signal_type = feature_state->signal_type; - auto end_time = state->end_time; - signal_database_->GetSamples( - signal_type, name_hash, start_time, end_time, - base::BindOnce(&ModelExecutionManagerImpl::OnGetSamplesForFeature, - weak_ptr_factory_.GetWeakPtr(), std::move(state), - std::move(feature_state))); -} - -void ModelExecutionManagerImpl::OnGetSamplesForFeature( - std::unique_ptr<ExecutionState> state, - std::unique_ptr<FeatureState> feature_state, - std::vector<SignalDatabase::Sample> samples) { - ModelExecutionTraceEvent trace_event( - "ModelExecutionManagerImpl::OnGetSamplesForFeature", *state); - base::Time process_start_time = clock_->Now(); - // HISTOGRAM_ENUM features might require us to filter out the result to only - // keep enum values that match the accepted list. If the accepted list is' - // empty, all histogram enum values are kept. - // The SignalDatabase does not currently support this type of data filter, - // so instead we are doing this here. - if (feature_state->signal_type == proto::SignalType::HISTOGRAM_ENUM) { - DCHECK(feature_state->accepted_enum_ids.has_value()); - feature_aggregator_->FilterEnumSamples(*feature_state->accepted_enum_ids, - samples); - } - - // We now have all the data required to process a single feature, so we can - // process it synchronously, and insert it into the - // ExecutorState::input_tensor so we can later pass it to the ML model - // executor. - std::vector<float> feature_data = feature_aggregator_->Process( - feature_state->signal_type, feature_state->aggregation, - feature_state->bucket_count, state->end_time, state->bucket_duration, - samples); - DCHECK_EQ(feature_state->tensor_length, feature_data.size()); - state->input_tensor.insert(state->input_tensor.end(), feature_data.begin(), - feature_data.end()); - - stats::RecordModelExecutionDurationFeatureProcessing( - state->segment_id, clock_->Now() - process_start_time); - - // Continue with the rest of the features. - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, - base::BindOnce(&ModelExecutionManagerImpl::ProcessInputFeatures, - weak_ptr_factory_.GetWeakPtr(), std::move(state))); + ExecuteModel(std::move(state)); } void ModelExecutionManagerImpl::ExecuteModel(
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager_impl.h b/components/segmentation_platform/internal/execution/model_execution_manager_impl.h index 22c418c..95be2dab 100644 --- a/components/segmentation_platform/internal/execution/model_execution_manager_impl.h +++ b/components/segmentation_platform/internal/execution/model_execution_manager_impl.h
@@ -30,6 +30,7 @@ namespace segmentation_platform { class FeatureAggregator; +class FeatureListQueryProcessor; class SignalDatabase; namespace proto { @@ -79,7 +80,6 @@ FRIEND_TEST_ALL_PREFIXES(SegmentationPlatformServiceImplTest, InitializationFlow); struct ExecutionState; - struct FeatureState; struct ModelExecutionTraceEvent; // Callback method for when the SegmentInfo (segment metadata) has been @@ -88,29 +88,19 @@ std::unique_ptr<ExecutionState> state, absl::optional<proto::SegmentInfo> segment_info); - // ProcessInputFeatures is the core function for processing all the required - // ML input features in the correct order. It fetches samples for one input at - // a time, makes sure the data is processed, and then is invoked again to - // process the next input. - void ProcessInputFeatures(std::unique_ptr<ExecutionState> state); + // Callback method for when the processing of the model metadata's feature + // list has completed, which either result in an error or a valid input tensor + // for executing the model. + void OnProcessingFeatureListComplete(std::unique_ptr<ExecutionState> state, + bool error, + const std::vector<float>& input_tensor); - // Function for processing the next UMAFeature type of input for ML model. - void ProcessNextUmaFeature(proto::UMAFeature feature, - std::unique_ptr<ExecutionState> state); - - // Callback method for when all relevant samples for a particular feature has - // been loaded. Processes the samples, and inserts them into the input tensor - // that is later given to the ML execution. - void OnGetSamplesForFeature(std::unique_ptr<ExecutionState> state, - std::unique_ptr<FeatureState> feature_state, - std::vector<SignalDatabase::Sample> samples); - - // ExecuteModel takes the current input tensor and passes it to the ML model - // for execution. + // ExecuteModel takes the current input tensor and passes it to the ML + // model for execution. void ExecuteModel(std::unique_ptr<ExecutionState> state); - // Callback method for when the model execution has completed which gives the - // end result to the initial ModelExecutionCallback passed to + // Callback method for when the model execution has completed which gives + // the end result to the initial ModelExecutionCallback passed to // ExecuteModel(...). void OnModelExecutionComplete(std::unique_ptr<ExecutionState> state, const absl::optional<float>& result); @@ -131,15 +121,15 @@ // Callback after fetching the current SegmentInfo from the // SegmentInfoDatabase. This is part of the flow for informing the // SegmentationModelUpdatedCallback about a changed model. - // Merges the PredictionResult from the previously stored SegmentInfo with the - // newly updated one, and stores the new version in the DB. + // Merges the PredictionResult from the previously stored SegmentInfo with + // the newly updated one, and stores the new version in the DB. void OnSegmentInfoFetchedForModelUpdate( optimization_guide::proto::OptimizationTarget segment_id, proto::SegmentationModelMetadata metadata, absl::optional<proto::SegmentInfo> segment_info); - // Callback after storing the updated version of the SegmentInfo. Responsible - // for invoking the SegmentationModelUpdatedCallback. + // Callback after storing the updated version of the SegmentInfo. + // Responsible for invoking the SegmentationModelUpdatedCallback. void OnUpdatedSegmentInfoStored(proto::SegmentInfo segment_info, bool success); @@ -156,8 +146,8 @@ // Main signal database for user actions and histograms. raw_ptr<SignalDatabase> signal_database_; - // The FeatureAggregator aggregates all the data based on metadata and input. - std::unique_ptr<FeatureAggregator> feature_aggregator_; + // Feature list processor for processing a model metadata's feature list. + std::unique_ptr<FeatureListQueryProcessor> feature_list_query_processor_; // Invoked whenever there is an update to any of the relevant ML models. SegmentationModelUpdatedCallback model_updated_callback_;
diff --git a/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc b/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc index b364dcd..7f134db 100644 --- a/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc +++ b/components/segmentation_platform/internal/execution/model_execution_manager_impl_unittest.cc
@@ -25,6 +25,7 @@ #include "components/segmentation_platform/internal/database/signal_database.h" #include "components/segmentation_platform/internal/database/test_segment_info_database.h" #include "components/segmentation_platform/internal/execution/feature_aggregator.h" +#include "components/segmentation_platform/internal/execution/mock_feature_aggregator.h" #include "components/segmentation_platform/internal/execution/model_execution_manager.h" #include "components/segmentation_platform/internal/execution/model_execution_status.h" #include "components/segmentation_platform/internal/execution/segmentation_model_handler.h" @@ -43,11 +44,6 @@ namespace segmentation_platform { using Sample = SignalDatabase::Sample; -namespace { -constexpr base::TimeDelta kOneSecond = base::Seconds(1); -constexpr base::TimeDelta kTwoSeconds = base::Seconds(2); -} // namespace - class MockSegmentInfoDatabase : public test::TestSegmentInfoDatabase { public: MOCK_METHOD(void, Initialize, (SuccessCallback callback), (override)); @@ -101,25 +97,6 @@ MOCK_METHOD(bool, ModelAvailable, (), (const override)); }; -class MockFeatureAggregator : public FeatureAggregator { - public: - MockFeatureAggregator() = default; - MOCK_METHOD(std::vector<float>, - Process, - (proto::SignalType signal_type, - proto::Aggregation aggregation, - uint64_t bucket_count, - const base::Time& end_time, - const base::TimeDelta& bucket_duration, - const std::vector<Sample>& samples), - (const override)); - MOCK_METHOD(void, - FilterEnumSamples, - (const std::vector<int32_t>& accepted_enum_ids, - std::vector<Sample>& samples), - (const override)); -}; - class ModelExecutionManagerTest : public testing::Test { public: ModelExecutionManagerTest() = default; @@ -229,52 +206,6 @@ ExecuteModel(std::make_pair(0, ModelExecutionStatus::kInvalidMetadata)); } -TEST_F(ModelExecutionManagerTest, SingleUserAction) { - auto segment_id = - OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; - auto unrelated_segment_id = - optimization_guide::proto::OPTIMIZATION_TARGET_SEGMENTATION_SHARE; - CreateModelExecutionManager({segment_id, unrelated_segment_id}, - base::DoNothing()); - - // Initialize with required metadata. - segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR); - base::TimeDelta bucket_duration = base::Hours(3); - - // Set up a single user action feature. - std::string user_action_name_1 = "some_action_1"; - segment_database_->AddUserActionFeature(segment_id, user_action_name_1, 2, 1, - proto::Aggregation::COUNT); - - // When the particular user action is looked up with the correct start time, - // end time, and aggregation type, return 3 samples. - std::vector<Sample> samples{ - {clock_.Now(), 0}, - {clock_.Now(), 0}, - {clock_.Now(), 0}, - }; - EXPECT_CALL(*signal_database_, - GetSamples(proto::SignalType::USER_ACTION, - base::HashMetricName(user_action_name_1), - StartTime(bucket_duration, 2), clock_.Now(), _)) - .WillOnce(RunOnceCallback<4>(samples)); - - // After retrieving the samples, they should be processed and aggregated. - EXPECT_CALL(*feature_aggregator_, - Process(proto::SignalType::USER_ACTION, proto::Aggregation::COUNT, - 2, clock_.Now(), bucket_duration, samples)) - .WillOnce(Return(std::vector<float>{3})); - - // The next step should be to execute the model. - EXPECT_CALL(FindHandler(segment_id), ModelAvailable()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(FindHandler(segment_id), - ExecuteModelWithInput(_, std::vector<float>{3})) - .WillOnce(RunOnceCallback<0>(absl::make_optional(0.8))); - - ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess)); -} - TEST_F(ModelExecutionManagerTest, ModelNotReady) { auto segment_id = OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; @@ -289,289 +220,6 @@ ExecuteModel(std::make_pair(0, ModelExecutionStatus::kExecutionError)); } -TEST_F(ModelExecutionManagerTest, MultipleFeatures) { - auto segment_id = - OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; - CreateModelExecutionManager({segment_id}, base::DoNothing()); - - // Initialize with required metadata. - segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR); - base::TimeDelta bucket_duration = base::Hours(3); - - // Set up 3 metadata feature, one of each signal type. - std::string user_action_name = "some_user_action"; - segment_database_->AddUserActionFeature(segment_id, user_action_name, 2, 1, - proto::Aggregation::COUNT); - std::string histogram_value_name = "some_histogram_value"; - segment_database_->AddHistogramValueFeature(segment_id, histogram_value_name, - 3, 1, proto::Aggregation::SUM); - std::string histogram_enum_name = "some_histogram_enum"; - segment_database_->AddHistogramEnumFeature(segment_id, histogram_enum_name, 4, - 1, proto::Aggregation::COUNT, {}); - - // First feature should be the user action. - std::vector<Sample> user_action_samples{ - {clock_.Now(), 0}, - {clock_.Now(), 0}, - {clock_.Now(), 0}, - }; - EXPECT_CALL(*signal_database_, - GetSamples(proto::SignalType::USER_ACTION, - base::HashMetricName(user_action_name), - StartTime(bucket_duration, 2), clock_.Now(), _)) - .WillOnce(RunOnceCallback<4>(user_action_samples)); - EXPECT_CALL(*feature_aggregator_, - Process(proto::SignalType::USER_ACTION, proto::Aggregation::COUNT, - 2, clock_.Now(), bucket_duration, user_action_samples)) - .WillOnce(Return(std::vector<float>{3})); - - // Second feature should be the value histogram. - std::vector<Sample> histogram_value_samples{ - {clock_.Now(), 1}, - {clock_.Now(), 2}, - {clock_.Now(), 3}, - }; - EXPECT_CALL(*signal_database_, - GetSamples(proto::SignalType::HISTOGRAM_VALUE, - base::HashMetricName(histogram_value_name), - StartTime(bucket_duration, 3), clock_.Now(), _)) - .WillOnce(RunOnceCallback<4>(histogram_value_samples)); - EXPECT_CALL( - *feature_aggregator_, - Process(proto::SignalType::HISTOGRAM_VALUE, proto::Aggregation::SUM, 3, - clock_.Now(), bucket_duration, histogram_value_samples)) - .WillOnce(Return(std::vector<float>{6})); - - // Third feature should be the value histogram. - std::vector<Sample> histogram_enum_samples{ - {clock_.Now(), 1}, - {clock_.Now(), 2}, - {clock_.Now(), 3}, - {clock_.Now(), 4}, - }; - EXPECT_CALL(*signal_database_, - GetSamples(proto::SignalType::HISTOGRAM_ENUM, - base::HashMetricName(histogram_enum_name), - StartTime(bucket_duration, 4), clock_.Now(), _)) - .WillOnce(RunOnceCallback<4>(histogram_enum_samples)); - EXPECT_CALL( - *feature_aggregator_, - Process(proto::SignalType::HISTOGRAM_ENUM, proto::Aggregation::COUNT, 4, - clock_.Now(), bucket_duration, histogram_enum_samples)) - .WillOnce(Return(std::vector<float>{4})); - - // The input tensor should contain all three values: 3, 6, and 4. - EXPECT_CALL(FindHandler(segment_id), ModelAvailable()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(FindHandler(segment_id), - ExecuteModelWithInput(_, std::vector<float>{3, 6, 4})) - .WillOnce(RunOnceCallback<0>(absl::make_optional(0.8))); - - ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess)); -} - -TEST_F(ModelExecutionManagerTest, SkipCollectionOnlyFeatures) { - auto segment_id = - OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; - CreateModelExecutionManager({segment_id}, base::DoNothing()); - - // Initialize with required metadata. - segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR); - base::TimeDelta bucket_duration = base::Hours(3); - - // Set up 3 metadata feature, one of each signal type. - std::string collected_user_action = "some_user_action"; - segment_database_->AddUserActionFeature(segment_id, collected_user_action, 1, - 1, proto::Aggregation::COUNT); - std::string no_collection_user_action = "no_collection_user_action"; - segment_database_->AddUserActionFeature(segment_id, no_collection_user_action, - 0, 0, proto::Aggregation::SUM); - std::string no_collection_histogram_value = "no_collection_histogram_value"; - segment_database_->AddHistogramValueFeature( - segment_id, no_collection_histogram_value, 0, 0, proto::Aggregation::SUM); - std::string no_collection_histogram_enum = "no_collection_histogram_enum"; - segment_database_->AddHistogramEnumFeature(segment_id, - no_collection_histogram_enum, 0, 0, - proto::Aggregation::SUM, {}); - std::string collected_histogram_value = "collected_histogram_value"; - segment_database_->AddHistogramValueFeature( - segment_id, collected_histogram_value, 1, 1, proto::Aggregation::SUM); - - // The first feature in use should be the very first feature. - std::vector<Sample> user_action_samples{ - {clock_.Now(), 0}, - {clock_.Now(), 0}, - {clock_.Now(), 0}, - }; - EXPECT_CALL(*signal_database_, - GetSamples(proto::SignalType::USER_ACTION, - base::HashMetricName(collected_user_action), - StartTime(bucket_duration, 1), clock_.Now(), _)) - .WillOnce(RunOnceCallback<4>(user_action_samples)); - EXPECT_CALL(*feature_aggregator_, - Process(proto::SignalType::USER_ACTION, proto::Aggregation::COUNT, - 1, clock_.Now(), bucket_duration, user_action_samples)) - .WillOnce(Return(std::vector<float>{3})); - - // The three features in the middle should all be ignored, so the next one - // should be the last feature. - std::vector<Sample> histogram_value_samples{ - {clock_.Now(), 1}, - {clock_.Now(), 2}, - {clock_.Now(), 3}, - }; - EXPECT_CALL(*signal_database_, - GetSamples(proto::SignalType::HISTOGRAM_VALUE, - base::HashMetricName(collected_histogram_value), - StartTime(bucket_duration, 1), clock_.Now(), _)) - .WillOnce(RunOnceCallback<4>(histogram_value_samples)); - EXPECT_CALL( - *feature_aggregator_, - Process(proto::SignalType::HISTOGRAM_VALUE, proto::Aggregation::SUM, 1, - clock_.Now(), bucket_duration, histogram_value_samples)) - .WillOnce(Return(std::vector<float>{6})); - - // The input tensor should contain only the first and last feature. - EXPECT_CALL(FindHandler(segment_id), ModelAvailable()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(FindHandler(segment_id), - ExecuteModelWithInput(_, std::vector<float>{3, 6})) - .WillOnce(RunOnceCallback<0>(absl::make_optional(0.8))); - - ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess)); -} - -TEST_F(ModelExecutionManagerTest, FilteredEnumSamples) { - auto segment_id = - OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; - CreateModelExecutionManager({segment_id}, base::DoNothing()); - - // Initialize with required metadata. - segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR); - base::TimeDelta bucket_duration = base::Hours(3); - - // Set up a single enum histogram feature. - std::string histogram_enum_name = "some_histogram_enum"; - std::vector<int32_t> accepted_enum_ids = {2, 4}; - segment_database_->AddHistogramEnumFeature(segment_id, histogram_enum_name, 4, - 1, proto::Aggregation::COUNT, - accepted_enum_ids); - - // When the particular enum histogram is looked up with the correct start - // time, end time, and aggregation type, return all 5 samples. - std::vector<Sample> histogram_enum_samples{ - {clock_.Now(), 1}, {clock_.Now(), 2}, {clock_.Now(), 3}, - {clock_.Now(), 4}, {clock_.Now(), 5}, - }; - EXPECT_CALL(*signal_database_, - GetSamples(proto::SignalType::HISTOGRAM_ENUM, - base::HashMetricName(histogram_enum_name), - StartTime(bucket_duration, 4), clock_.Now(), _)) - .WillOnce(RunOnceCallback<4>(histogram_enum_samples)); - // The executor must first filter the enum samples. - std::vector<Sample> filtered_enum_samples{ - {clock_.Now(), 2}, - {clock_.Now(), 4}, - }; - EXPECT_CALL(*feature_aggregator_, - FilterEnumSamples(accepted_enum_ids, histogram_enum_samples)) - .WillOnce(SetArgReferee<1>(filtered_enum_samples)); - // Only filtered_enum_samples should be processed. - EXPECT_CALL( - *feature_aggregator_, - Process(proto::SignalType::HISTOGRAM_ENUM, proto::Aggregation::COUNT, 4, - clock_.Now(), bucket_duration, filtered_enum_samples)) - .WillOnce(Return(std::vector<float>{2})); - - // The input tensor should contain a single value. - EXPECT_CALL(FindHandler(segment_id), ModelAvailable()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(FindHandler(segment_id), - ExecuteModelWithInput(_, std::vector<float>{2})) - .WillOnce(RunOnceCallback<0>(absl::make_optional(0.8))); - - ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess)); -} - -TEST_F(ModelExecutionManagerTest, MultipleFeaturesWithMultipleBuckets) { - auto segment_id = - OptimizationTarget::OPTIMIZATION_TARGET_SEGMENTATION_NEW_TAB; - CreateModelExecutionManager({segment_id}, base::DoNothing()); - - // Initialize with required metadata. - segment_database_->SetBucketDuration(segment_id, 3, proto::TimeUnit::HOUR); - base::TimeDelta bucket_duration = base::Hours(3); - - // Set up metadata features where bucket_count is not equal to 1. - std::string user_action_name = "some_user_action"; - // 3 buckets - segment_database_->AddUserActionFeature(segment_id, user_action_name, 3, 3, - proto::Aggregation::BUCKETED_COUNT); - std::string histogram_value_name = "some_histogram_value"; - // 4 buckets - segment_database_->AddHistogramValueFeature( - segment_id, histogram_value_name, 4, 4, - proto::Aggregation::BUCKETED_COUNT_BOOLEAN); - - // First feature should be the user action. The timestamp is set to three - // different buckets. - std::vector<Sample> user_action_samples{ - {clock_.Now(), 0}, - {clock_.Now() - kOneSecond, 0}, - {clock_.Now() - bucket_duration, 0}, - {clock_.Now() - bucket_duration - kOneSecond, 0}, - {clock_.Now() - bucket_duration - kTwoSeconds, 0}, - {clock_.Now() - bucket_duration * 2, 0}, - {clock_.Now() - bucket_duration * 2 - kOneSecond, 0}, - {clock_.Now() - bucket_duration * 2 - kTwoSeconds, 0}, - }; - EXPECT_CALL(*signal_database_, - GetSamples(proto::SignalType::USER_ACTION, - base::HashMetricName(user_action_name), - StartTime(bucket_duration, 3), clock_.Now(), _)) - .WillOnce(RunOnceCallback<4>(user_action_samples)); - EXPECT_CALL(*feature_aggregator_, - Process(proto::SignalType::USER_ACTION, - proto::Aggregation::BUCKETED_COUNT, 3, clock_.Now(), - bucket_duration, user_action_samples)) - .WillOnce(Return(std::vector<float>{1, 2, 3})); - - // Second feature should be the value histogram. The timestamp is set to four - // different buckets. - std::vector<Sample> histogram_value_samples{ - {clock_.Now(), 1}, - {clock_.Now() - kOneSecond, 2}, - {clock_.Now() - bucket_duration, 3}, - {clock_.Now() - bucket_duration - kOneSecond, 4}, - {clock_.Now() - bucket_duration - kTwoSeconds, 5}, - {clock_.Now() - bucket_duration * 2, 6}, - {clock_.Now() - bucket_duration * 2 - kOneSecond, 7}, - {clock_.Now() - bucket_duration * 2 - kTwoSeconds, 8}, - {clock_.Now() - bucket_duration * 3, 9}, - {clock_.Now() - bucket_duration * 3 - kOneSecond, 10}, - {clock_.Now() - bucket_duration * 3 - kTwoSeconds, 11}, - }; - EXPECT_CALL(*signal_database_, - GetSamples(proto::SignalType::HISTOGRAM_VALUE, - base::HashMetricName(histogram_value_name), - StartTime(bucket_duration, 4), clock_.Now(), _)) - .WillOnce(RunOnceCallback<4>(histogram_value_samples)); - EXPECT_CALL(*feature_aggregator_, - Process(proto::SignalType::HISTOGRAM_VALUE, - proto::Aggregation::BUCKETED_COUNT_BOOLEAN, 4, - clock_.Now(), bucket_duration, histogram_value_samples)) - .WillOnce(Return(std::vector<float>{4, 5, 6, 7})); - - // The input tensor should contain all values flattened to a single vector. - EXPECT_CALL(FindHandler(segment_id), ModelAvailable()) - .WillRepeatedly(Return(true)); - EXPECT_CALL(FindHandler(segment_id), - ExecuteModelWithInput(_, std::vector<float>{1, 2, 3, 4, 5, 6, 7})) - .WillOnce(RunOnceCallback<0>(absl::make_optional(0.8))); - - ExecuteModel(std::make_pair(0.8, ModelExecutionStatus::kSuccess)); -} - TEST_F(ModelExecutionManagerTest, OnSegmentationModelUpdatedInvalidMetadata) { // Use a MockSegmentInfoDatabase for this test in particular, to verify that // it is never used.
diff --git a/components/segmentation_platform/internal/execution/uma_feature_processor.cc b/components/segmentation_platform/internal/execution/uma_feature_processor.cc new file mode 100644 index 0000000..dfdf14372 --- /dev/null +++ b/components/segmentation_platform/internal/execution/uma_feature_processor.cc
@@ -0,0 +1,118 @@ +// Copyright 2022 The Chromium 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/segmentation_platform/internal/execution/uma_feature_processor.h" + +#include "base/bind.h" +#include "base/location.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/timer/elapsed_timer.h" +#include "components/segmentation_platform/internal/database/metadata_utils.h" +#include "components/segmentation_platform/internal/execution/feature_processor_state.h" +#include "components/segmentation_platform/internal/proto/model_metadata.pb.h" +#include "components/segmentation_platform/internal/stats.h" + +namespace segmentation_platform { + +UmaFeatureProcessor::UmaFeatureProcessor( + SignalDatabase* signal_database, + std::unique_ptr<FeatureAggregator> feature_aggregator) + : signal_database_(signal_database), + feature_aggregator_(std::move(feature_aggregator)) {} + +UmaFeatureProcessor::~UmaFeatureProcessor() = default; + +void UmaFeatureProcessor::ProcessUmaFeature( + const proto::UMAFeature& feature, + std::unique_ptr<FeatureProcessorState> feature_processor_state, + FeatureListQueryProcessorCallback callback) { + // Skip collection-only features. + if (feature.bucket_count() == 0) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(std::move(callback), + std::move(feature_processor_state))); + return; + } + + // Validate the proto::UMAFeature metadata. + if (metadata_utils::ValidateMetadataUmaFeature(feature) != + metadata_utils::ValidationResult::kValidationSuccess) { + feature_processor_state->SetError(); + feature_processor_state->RunCallback(); + return; + } + + auto name_hash = feature.name_hash(); + + // Enum histograms can optionally only accept some of the enum values. + // While the proto::UMAFeature is available, capture a vector of the + // accepted enum values. An empty vector is ignored (all values are + // considered accepted). + std::vector<int32_t> accepted_enum_ids{}; + if (feature.type() == proto::SignalType::HISTOGRAM_ENUM) { + for (int i = 0; i < feature.enum_ids_size(); ++i) + accepted_enum_ids.emplace_back(feature.enum_ids(i)); + } + + // Only fetch data that is relevant for the current proto::UMAFeature, since + // the FeatureAggregator assumes that only relevant data is given to it. + base::TimeDelta duration = + feature_processor_state->bucket_duration() * feature.bucket_count(); + base::Time start_time = feature_processor_state->prediction_time() - duration; + + // Fetch the relevant samples for the current proto::UMAFeature. Once the + // result has come back, it will be processed and inserted into the + // FeatureProcessorState::input_tensor and will then invoke + // ProcessInputFeatures(...) again to ensure we continue until all features + // have been processed. Note: All parameters from the FeatureProcessorState + // need to be captured locally before invoking GetSamples, because the state + // is moved with the callback, and the order of the move and accessing the + // members while invoking GetSamples is not guaranteed. + auto signal_type = feature.type(); + auto prediction_time = feature_processor_state->prediction_time(); + signal_database_->GetSamples( + signal_type, name_hash, start_time, prediction_time, + base::BindOnce(&UmaFeatureProcessor::OnGetSamplesForUmaFeature, + weak_ptr_factory_.GetWeakPtr(), std::move(callback), + std::move(feature_processor_state), feature, + accepted_enum_ids)); +} + +void UmaFeatureProcessor::OnGetSamplesForUmaFeature( + FeatureListQueryProcessorCallback callback, + std::unique_ptr<FeatureProcessorState> feature_processor_state, + const proto::UMAFeature& feature, + const std::vector<int32_t>& accepted_enum_ids, + std::vector<SignalDatabase::Sample> samples) { + base::ElapsedTimer timer; + // HISTOGRAM_ENUM features might require us to filter out the result to only + // keep enum values that match the accepted list. If the accepted list is' + // empty, all histogram enum values are kept. + // The SignalDatabase does not currently support this type of data filter, + // so instead we are doing this here. + if (feature.type() == proto::SignalType::HISTOGRAM_ENUM) { + feature_aggregator_->FilterEnumSamples(accepted_enum_ids, samples); + } + + // We now have all the data required to process a single feature, so we can + // process it synchronously, and insert it into the + // FeatureProcessorState::input_tensor so we can later pass it to the ML model + // executor. + std::vector<float> feature_data = feature_aggregator_->Process( + feature.type(), feature.aggregation(), feature.bucket_count(), + feature_processor_state->prediction_time(), + feature_processor_state->bucket_duration(), samples); + + DCHECK_EQ(feature.tensor_length(), feature_data.size()); + feature_processor_state->AppendInputTensor(feature_data); + + stats::RecordModelExecutionDurationFeatureProcessing( + feature_processor_state->segment_id(), timer.Elapsed()); + + // Continue with the rest of the features. + std::move(callback).Run(std::move(feature_processor_state)); +} + +} // namespace segmentation_platform
diff --git a/components/segmentation_platform/internal/execution/uma_feature_processor.h b/components/segmentation_platform/internal/execution/uma_feature_processor.h new file mode 100644 index 0000000..74152f2 --- /dev/null +++ b/components/segmentation_platform/internal/execution/uma_feature_processor.h
@@ -0,0 +1,65 @@ +// Copyright 2022 The Chromium 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_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_UMA_FEATURE_PROCESSOR_H_ +#define COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_UMA_FEATURE_PROCESSOR_H_ + +#include <memory> +#include <vector> + +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "components/optimization_guide/proto/models.pb.h" +#include "components/segmentation_platform/internal/database/signal_database.h" +#include "components/segmentation_platform/internal/execution/feature_aggregator.h" +#include "components/segmentation_platform/internal/proto/model_metadata.pb.h" + +namespace segmentation_platform { +class FeatureProcessorState; + +// UmaFeatureProcessor takes an UMAFeature type of input, fetches samples from +// the SignalDatabase (raw signals) databases, and computes an input tensor to +// use when executing the ML model. +class UmaFeatureProcessor { + public: + UmaFeatureProcessor(SignalDatabase* signal_database, + std::unique_ptr<FeatureAggregator> feature_aggregator); + virtual ~UmaFeatureProcessor(); + + // Disallow copy/assign. + UmaFeatureProcessor(const UmaFeatureProcessor&) = delete; + UmaFeatureProcessor& operator=(const UmaFeatureProcessor&) = delete; + + using FeatureListQueryProcessorCallback = + base::OnceCallback<void(std::unique_ptr<FeatureProcessorState>)>; + + // Function for processing the next UMAFeature type of input for ML model. + void ProcessUmaFeature( + const proto::UMAFeature& feature, + std::unique_ptr<FeatureProcessorState> feature_processor_state, + FeatureListQueryProcessorCallback callback); + + private: + // Callback method for when all relevant samples for a particular feature has + // been loaded. Processes the samples, and inserts them into the input tensor + // that is later given to the ML execution. + void OnGetSamplesForUmaFeature( + FeatureListQueryProcessorCallback callback, + std::unique_ptr<FeatureProcessorState> feature_processor_state, + const proto::UMAFeature& feature, + const std::vector<int32_t>& accepted_enum_ids, + std::vector<SignalDatabase::Sample> samples); + + // Main signal database for user actions and histograms. + raw_ptr<SignalDatabase> signal_database_; + + // The FeatureAggregator aggregates all the data based on metadata and input. + std::unique_ptr<FeatureAggregator> feature_aggregator_; + + base::WeakPtrFactory<UmaFeatureProcessor> weak_ptr_factory_{this}; +}; + +} // namespace segmentation_platform + +#endif // COMPONENTS_SEGMENTATION_PLATFORM_INTERNAL_EXECUTION_UMA_FEATURE_PROCESSOR_H_
diff --git a/components/services/app_service/public/cpp/BUILD.gn b/components/services/app_service/public/cpp/BUILD.gn index cfad6f9..b7ef91e 100644 --- a/components/services/app_service/public/cpp/BUILD.gn +++ b/components/services/app_service/public/cpp/BUILD.gn
@@ -205,6 +205,7 @@ ] deps = [ + ":app_types", "//base", "//components/services/app_service/public/mojom", "//third_party/blink/public/common",
diff --git a/components/services/app_service/public/cpp/app_registry_cache.cc b/components/services/app_service/public/cpp/app_registry_cache.cc index c0effb4..eb13fcd 100644 --- a/components/services/app_service/public/cpp/app_registry_cache.cc +++ b/components/services/app_service/public/cpp/app_registry_cache.cc
@@ -90,7 +90,7 @@ OnAppTypeInitialized(); } -void AppRegistryCache::OnApps(std::vector<std::unique_ptr<App>> deltas, +void AppRegistryCache::OnApps(std::vector<AppPtr> deltas, apps::AppType app_type, bool should_notify_initialized) { DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker_); @@ -108,7 +108,7 @@ DoOnApps(std::move(deltas)); while (!deltas_pending_.empty()) { - std::vector<std::unique_ptr<App>> pending; + std::vector<AppPtr> pending; pending.swap(deltas_pending_); DoOnApps(std::move(pending)); } @@ -179,7 +179,7 @@ mojom_deltas_in_progress_.clear(); } -void AppRegistryCache::DoOnApps(std::vector<std::unique_ptr<App>> deltas) { +void AppRegistryCache::DoOnApps(std::vector<AppPtr> deltas) { // Merge any deltas elements that have the same app_id. If an observer's // OnAppUpdate calls back into this AppRegistryCache then we can therefore // present a single delta for any given app_id.
diff --git a/components/services/app_service/public/cpp/app_registry_cache.h b/components/services/app_service/public/cpp/app_registry_cache.h index 799a93a8..1c6c37d 100644 --- a/components/services/app_service/public/cpp/app_registry_cache.h +++ b/components/services/app_service/public/cpp/app_registry_cache.h
@@ -115,7 +115,7 @@ void OnApps(std::vector<apps::mojom::AppPtr> deltas, apps::mojom::AppType app_type, bool should_notify_initialized); - void OnApps(std::vector<std::unique_ptr<App>> deltas, + void OnApps(std::vector<AppPtr> deltas, apps::AppType app_type, bool should_notify_initialized); @@ -249,7 +249,7 @@ friend class PublisherTest; void DoOnApps(std::vector<apps::mojom::AppPtr> deltas); - void DoOnApps(std::vector<std::unique_ptr<App>> deltas); + void DoOnApps(std::vector<AppPtr> deltas); // NOINLINE should force this function to appear on the stack in crash dumps. // https://crbug.com/1237267. @@ -259,7 +259,7 @@ // Maps from app_id to the latest state: the "sum" of all previous deltas. std::map<std::string, apps::mojom::AppPtr> mojom_states_; - std::map<std::string, std::unique_ptr<App>> states_; + std::map<std::string, AppPtr> states_; // Track the deltas being processed or are about to be processed by OnApps. // They are separate to manage the "notification and merging might be delayed @@ -280,7 +280,7 @@ std::map<std::string, apps::mojom::App*> mojom_deltas_in_progress_; std::vector<apps::mojom::AppPtr> mojom_deltas_pending_; std::map<std::string, App*> deltas_in_progress_; - std::vector<std::unique_ptr<App>> deltas_pending_; + std::vector<AppPtr> deltas_pending_; // Saves app types which will finish initialization, and OnAppTypeInitialized // will be called to notify observers.
diff --git a/components/services/app_service/public/cpp/app_registry_cache_unittest.cc b/components/services/app_service/public/cpp/app_registry_cache_unittest.cc index c6c8146..13708e7 100644 --- a/components/services/app_service/public/cpp/app_registry_cache_unittest.cc +++ b/components/services/app_service/public/cpp/app_registry_cache_unittest.cc
@@ -14,11 +14,11 @@ class AppRegistryCacheTest : public testing::Test { public: - std::unique_ptr<App> MakeApp(const char* app_id, - const char* name, - Readiness readiness = Readiness::kUnknown, - uint64_t timeline = 0) { - std::unique_ptr<App> app = std::make_unique<App>(AppType::kArc, app_id); + AppPtr MakeApp(const char* app_id, + const char* name, + Readiness readiness = Readiness::kUnknown, + uint64_t timeline = 0) { + auto app = std::make_unique<App>(AppType::kArc, app_id); app->readiness = readiness; app->name = name; app->icon_key = IconKey(timeline, /*resource_id=*/0, /*icon_effects=*/0); @@ -74,7 +74,7 @@ TEST_F(AppRegistryCacheTest, OnApps) { AppRegistryCache cache; - std::vector<std::unique_ptr<App>> deltas; + std::vector<AppPtr> deltas; deltas.push_back(MakeApp("a", "apple")); deltas.push_back(MakeApp("b", "banana", Readiness::kReady)); deltas.push_back(MakeApp("c", "cherry", Readiness::kDisabledByPolicy, @@ -121,7 +121,7 @@ TEST_F(AppRegistryCacheTest, Removed) { AppRegistryCache cache; - std::vector<std::unique_ptr<App>> apps; + std::vector<AppPtr> apps; apps.push_back(MakeApp("app", "app", Readiness::kReady)); cache.OnApps(std::move(apps), AppType::kUnknown, false /* should_notify_initialized */);
diff --git a/components/services/app_service/public/cpp/app_types.cc b/components/services/app_service/public/cpp/app_types.cc index b30acbc..abacfc3 100644 --- a/components/services/app_service/public/cpp/app_types.cc +++ b/components/services/app_service/public/cpp/app_types.cc
@@ -11,8 +11,8 @@ App::~App() = default; -std::unique_ptr<App> App::Clone() const { - std::unique_ptr<App> app = std::make_unique<App>(app_type, app_id); +AppPtr App::Clone() const { + auto app = std::make_unique<App>(app_type, app_id); app->readiness = readiness; app->name = name; @@ -146,6 +146,29 @@ } } +apps::mojom::Readiness ConvertReadinessToMojomReadiness(Readiness readiness) { + switch (readiness) { + case Readiness::kUnknown: + return apps::mojom::Readiness::kUnknown; + case Readiness::kReady: + return apps::mojom::Readiness::kReady; + case Readiness::kDisabledByBlocklist: + return apps::mojom::Readiness::kDisabledByBlocklist; + case Readiness::kDisabledByPolicy: + return apps::mojom::Readiness::kDisabledByPolicy; + case Readiness::kDisabledByUser: + return apps::mojom::Readiness::kDisabledByUser; + case Readiness::kTerminated: + return apps::mojom::Readiness::kTerminated; + case Readiness::kUninstalledByUser: + return apps::mojom::Readiness::kUninstalledByUser; + case Readiness::kRemoved: + return apps::mojom::Readiness::kRemoved; + case Readiness::kUninstalledByMigration: + return apps::mojom::Readiness::kUninstalledByMigration; + } +} + InstallReason ConvertMojomInstallReasonToInstallReason( apps::mojom::InstallReason mojom_install_reason) { switch (mojom_install_reason) { @@ -168,6 +191,28 @@ } } +apps::mojom::InstallReason ConvertInstallReasonToMojomInstallReason( + InstallReason install_reason) { + switch (install_reason) { + case InstallReason::kUnknown: + return apps::mojom::InstallReason::kUnknown; + case InstallReason::kSystem: + return apps::mojom::InstallReason::kSystem; + case InstallReason::kPolicy: + return apps::mojom::InstallReason::kPolicy; + case InstallReason::kOem: + return apps::mojom::InstallReason::kOem; + case InstallReason::kDefault: + return apps::mojom::InstallReason::kDefault; + case InstallReason::kSync: + return apps::mojom::InstallReason::kSync; + case InstallReason::kUser: + return apps::mojom::InstallReason::kUser; + case InstallReason::kSubApp: + return apps::mojom::InstallReason::kSubApp; + } +} + InstallSource ConvertMojomInstallSourceToInstallSource( apps::mojom::InstallSource mojom_install_source) { switch (mojom_install_source) { @@ -186,6 +231,24 @@ } } +apps::mojom::InstallSource ConvertInstallSourceToMojomInstallSource( + InstallSource install_source) { + switch (install_source) { + case InstallSource::kUnknown: + return apps::mojom::InstallSource::kUnknown; + case InstallSource::kSystem: + return apps::mojom::InstallSource::kSystem; + case InstallSource::kSync: + return apps::mojom::InstallSource::kSync; + case InstallSource::kPlayStore: + return apps::mojom::InstallSource::kPlayStore; + case InstallSource::kChromeWebStore: + return apps::mojom::InstallSource::kChromeWebStore; + case InstallSource::kBrowser: + return apps::mojom::InstallSource::kBrowser; + } +} + WindowMode ConvertMojomWindowModeToWindowMode( apps::mojom::WindowMode mojom_window_mode) { switch (mojom_window_mode) { @@ -200,6 +263,20 @@ } } +apps::mojom::WindowMode ConvertWindowModeToMojomWindowMode( + WindowMode window_mode) { + switch (window_mode) { + case WindowMode::kUnknown: + return apps::mojom::WindowMode::kUnknown; + case WindowMode::kWindow: + return apps::mojom::WindowMode::kWindow; + case WindowMode::kBrowser: + return apps::mojom::WindowMode::kBrowser; + case WindowMode::kTabbedWindow: + return apps::mojom::WindowMode::kTabbedWindow; + } +} + absl::optional<bool> GetOptionalBool( const apps::mojom::OptionalBool& mojom_optional_bool) { absl::optional<bool> optional_bool; @@ -209,10 +286,17 @@ return optional_bool; } -std::unique_ptr<App> ConvertMojomAppToApp( - const apps::mojom::AppPtr& mojom_app) { +apps::mojom::OptionalBool GetMojomOptionalBool( + const absl::optional<bool>& optional_bool) { + return optional_bool.has_value() + ? (optional_bool.value() ? apps::mojom::OptionalBool::kTrue + : apps::mojom::OptionalBool::kFalse) + : apps::mojom::OptionalBool::kUnknown; +} + +AppPtr ConvertMojomAppToApp(const apps::mojom::AppPtr& mojom_app) { DCHECK(mojom_app); - std::unique_ptr<App> app = std::make_unique<App>( + auto app = std::make_unique<App>( ConvertMojomAppTypToAppType(mojom_app->app_type), mojom_app->app_id); app->readiness = ConvertMojomReadinessToReadiness(mojom_app->readiness); @@ -278,4 +362,64 @@ return app; } +apps::mojom::AppPtr ConvertAppToMojomApp(const AppPtr& app) { + auto mojom_app = apps::mojom::App::New(); + mojom_app->app_type = ConvertAppTypeToMojomAppType(app->app_type); + mojom_app->app_id = app->app_id; + mojom_app->readiness = ConvertReadinessToMojomReadiness(app->readiness); + mojom_app->name = app->name; + mojom_app->short_name = app->short_name; + mojom_app->publisher_id = app->publisher_id; + mojom_app->description = app->description; + mojom_app->version = app->version; + mojom_app->additional_search_terms = app->additional_search_terms; + + if (app->icon_key.has_value()) { + mojom_app->icon_key = ConvertIconKeyToMojomIconKey(app->icon_key.value()); + } + + mojom_app->last_launch_time = app->last_launch_time; + mojom_app->install_time = app->install_time; + + for (const auto& permission : app->permissions) { + if (permission) { + mojom_app->permissions.push_back( + ConvertPermissionToMojomPermission(permission)); + } + } + + mojom_app->install_reason = + ConvertInstallReasonToMojomInstallReason(app->install_reason); + mojom_app->install_source = + ConvertInstallSourceToMojomInstallSource(app->install_source); + mojom_app->policy_id = app->policy_id; + mojom_app->is_platform_app = GetMojomOptionalBool(app->is_platform_app); + mojom_app->recommendable = GetMojomOptionalBool(app->recommendable); + mojom_app->searchable = GetMojomOptionalBool(app->searchable); + mojom_app->show_in_launcher = GetMojomOptionalBool(app->show_in_launcher); + mojom_app->show_in_shelf = GetMojomOptionalBool(app->show_in_shelf); + mojom_app->show_in_search = GetMojomOptionalBool(app->show_in_search); + mojom_app->show_in_management = GetMojomOptionalBool(app->show_in_management); + mojom_app->handles_intents = GetMojomOptionalBool(app->handles_intents); + mojom_app->allow_uninstall = GetMojomOptionalBool(app->allow_uninstall); + mojom_app->has_badge = GetMojomOptionalBool(app->has_badge); + mojom_app->paused = GetMojomOptionalBool(app->paused); + + for (const auto& intent_filter : app->intent_filters) { + if (intent_filter) { + mojom_app->intent_filters.push_back( + ConvertIntentFilterToMojomIntentFilter(intent_filter)); + } + } + + mojom_app->resize_locked = GetMojomOptionalBool(app->resize_locked); + mojom_app->window_mode = ConvertWindowModeToMojomWindowMode(app->window_mode); + + if (app->run_on_os_login.has_value()) { + mojom_app->run_on_os_login = + ConvertRunOnOsLoginToMojomRunOnOsLogin(app->run_on_os_login.value()); + } + return mojom_app; +} + } // namespace apps
diff --git a/components/services/app_service/public/cpp/app_types.h b/components/services/app_service/public/cpp/app_types.h index 1120cac..0e7fdc2a 100644 --- a/components/services/app_service/public/cpp/app_types.h +++ b/components/services/app_service/public/cpp/app_types.h
@@ -203,6 +203,8 @@ // `AppUpdate` class should also be updated. }; +using AppPtr = std::unique_ptr<App>; + // TODO(crbug.com/1253250): Remove these functions after migrating to non-mojo // AppService. COMPONENT_EXPORT(APP_TYPES) @@ -216,23 +218,45 @@ apps::mojom::Readiness mojom_readiness); COMPONENT_EXPORT(APP_TYPES) +apps::mojom::Readiness ConvertReadinessToMojomReadiness(Readiness readiness); + +COMPONENT_EXPORT(APP_TYPES) InstallReason ConvertMojomInstallReasonToInstallReason( apps::mojom::InstallReason mojom_install_reason); COMPONENT_EXPORT(APP_TYPES) +apps::mojom::InstallReason ConvertInstallReasonToMojomInstallReason( + InstallReason install_reason); + +COMPONENT_EXPORT(APP_TYPES) InstallSource ConvertMojomInstallSourceToInstallSource( apps::mojom::InstallSource mojom_install_source); COMPONENT_EXPORT(APP_TYPES) +apps::mojom::InstallSource ConvertInstallSourceToMojomInstallSource( + InstallSource install_source); + +COMPONENT_EXPORT(APP_TYPES) WindowMode ConvertMojomWindowModeToWindowMode( apps::mojom::WindowMode mojom_window_mode); COMPONENT_EXPORT(APP_TYPES) +apps::mojom::WindowMode ConvertWindowModeToMojomWindowMode( + WindowMode mojom_window_mode); + +COMPONENT_EXPORT(APP_TYPES) absl::optional<bool> GetOptionalBool( const apps::mojom::OptionalBool& mojom_optional_bool); COMPONENT_EXPORT(APP_TYPES) -std::unique_ptr<App> ConvertMojomAppToApp(const apps::mojom::AppPtr& mojom_app); +absl::optional<bool> GetMojomOptionalBool( + const apps::mojom::OptionalBool& mojom_optional_bool); + +COMPONENT_EXPORT(APP_TYPES) +AppPtr ConvertMojomAppToApp(const apps::mojom::AppPtr& mojom_app); + +COMPONENT_EXPORT(APP_TYPES) +apps::mojom::AppPtr ConvertAppToMojomApp(const AppPtr& app); } // namespace apps
diff --git a/components/services/app_service/public/cpp/app_update_mojom_unittest.cc b/components/services/app_service/public/cpp/app_update_mojom_unittest.cc index edb7a91..3e2bf01 100644 --- a/components/services/app_service/public/cpp/app_update_mojom_unittest.cc +++ b/components/services/app_service/public/cpp/app_update_mojom_unittest.cc
@@ -2,8 +2,12 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "components/services/app_service/public/cpp/app_types.h" #include "components/services/app_service/public/cpp/app_update.h" +#include "components/services/app_service/public/cpp/icon_types.h" +#include "components/services/app_service/public/cpp/intent_filter.h" #include "components/services/app_service/public/cpp/intent_filter_util.h" +#include "components/services/app_service/public/cpp/permission.h" #include "testing/gtest/include/gtest/gtest.h" namespace { @@ -1003,3 +1007,168 @@ TestAppUpdate(state.get(), delta.get()); } + +TEST_F(AppUpdateMojomTest, AppConvert) { + apps::mojom::AppPtr input = apps::mojom::App::New(); + input->app_type = apps::mojom::AppType::kWeb; + input->app_id = "abcdefg"; + input->readiness = apps::mojom::Readiness::kReady; + input->name = "lacros test name"; + input->short_name = "lacros test name"; + input->publisher_id = "publisher_id"; + input->description = "description"; + input->version = "version"; + input->additional_search_terms = {"1", "2"}; + + auto icon_key = apps::mojom::IconKey::New(); + icon_key->timeline = 1; + icon_key->icon_effects = 2; + input->icon_key = std::move(icon_key); + + input->last_launch_time = base::Time() + base::Days(1); + input->install_time = base::Time() + base::Days(2); + + input->install_reason = apps::mojom::InstallReason::kUser; + input->policy_id = "https://app.site/alpha"; + input->is_platform_app = apps::mojom::OptionalBool::kFalse; + input->recommendable = apps::mojom::OptionalBool::kTrue; + input->searchable = apps::mojom::OptionalBool::kTrue; + input->paused = apps::mojom::OptionalBool::kFalse; + input->show_in_launcher = apps::mojom::OptionalBool::kTrue; + input->show_in_shelf = apps::mojom::OptionalBool::kTrue; + input->show_in_search = apps::mojom::OptionalBool::kTrue; + input->show_in_management = apps::mojom::OptionalBool::kTrue; + input->has_badge = apps::mojom::OptionalBool::kUnknown; + input->paused = apps::mojom::OptionalBool::kFalse; + + auto intent_filter = apps::mojom::IntentFilter::New(); + apps_util::AddSingleValueCondition( + apps::mojom::ConditionType::kScheme, "https", + apps::mojom::PatternMatchType::kNone, intent_filter); + intent_filter->activity_name = "activity_name"; + intent_filter->activity_label = "activity_label"; + input->intent_filters.push_back(std::move(intent_filter)); + + input->window_mode = apps::mojom::WindowMode::kWindow; + + auto permission = apps::mojom::Permission::New(); + permission->permission_type = apps::mojom::PermissionType::kCamera; + permission->value = apps::mojom::PermissionValue::New(); + permission->value->set_bool_value(true); + permission->is_managed = true; + input->permissions.push_back(std::move(permission)); + + input->allow_uninstall = apps::mojom::OptionalBool::kTrue; + input->handles_intents = apps::mojom::OptionalBool::kTrue; + + auto output = apps::ConvertMojomAppToApp(input); + + EXPECT_EQ(output->app_type, apps::AppType::kWeb); + EXPECT_EQ(output->app_id, "abcdefg"); + EXPECT_EQ(output->readiness, apps::Readiness::kReady); + EXPECT_EQ(output->name, "lacros test name"); + EXPECT_EQ(output->short_name, "lacros test name"); + EXPECT_EQ(output->publisher_id, "publisher_id"); + EXPECT_EQ(output->description, "description"); + EXPECT_EQ(output->version, "version"); + EXPECT_EQ(output->additional_search_terms, input->additional_search_terms); + + EXPECT_EQ(output->icon_key->timeline, 1U); + EXPECT_EQ(output->icon_key->icon_effects, 2U); + + EXPECT_EQ(output->last_launch_time, base::Time() + base::Days(1)); + EXPECT_EQ(output->install_time, base::Time() + base::Days(2)); + + EXPECT_EQ(output->install_reason, apps::InstallReason::kUser); + EXPECT_EQ(output->policy_id, "https://app.site/alpha"); + EXPECT_FALSE(output->is_platform_app.value()); + EXPECT_TRUE(output->recommendable.value()); + EXPECT_TRUE(output->searchable.value()); + EXPECT_FALSE(output->paused.value()); + EXPECT_TRUE(output->show_in_launcher.value()); + EXPECT_TRUE(output->show_in_shelf.value()); + EXPECT_TRUE(output->show_in_search.value()); + EXPECT_TRUE(output->show_in_management.value()); + EXPECT_FALSE(output->has_badge.has_value()); + EXPECT_FALSE(output->paused.value()); + + ASSERT_EQ(output->intent_filters.size(), 1U); + auto& filter = output->intent_filters[0]; + ASSERT_EQ(filter->conditions.size(), 1U); + auto& condition = filter->conditions[0]; + EXPECT_EQ(condition->condition_type, apps::ConditionType::kScheme); + ASSERT_EQ(condition->condition_values.size(), 1U); + EXPECT_EQ(condition->condition_values[0]->value, "https"); + EXPECT_EQ(condition->condition_values[0]->match_type, + apps::PatternMatchType::kNone); + EXPECT_EQ(filter->activity_name, "activity_name"); + EXPECT_EQ(filter->activity_label, "activity_label"); + + EXPECT_EQ(output->window_mode, apps::WindowMode::kWindow); + + ASSERT_EQ(output->permissions.size(), 1U); + auto& out_permission = output->permissions[0]; + EXPECT_EQ(out_permission->permission_type, apps::PermissionType::kCamera); + ASSERT_TRUE(out_permission->value->bool_value.has_value()); + EXPECT_TRUE(out_permission->value->bool_value.value()); + EXPECT_TRUE(out_permission->is_managed); + + EXPECT_TRUE(output->allow_uninstall.value()); + EXPECT_TRUE(output->handles_intents.value()); + + auto mojom_app = apps::ConvertAppToMojomApp(output); + + EXPECT_EQ(mojom_app->app_type, apps::mojom::AppType::kWeb); + EXPECT_EQ(mojom_app->app_id, "abcdefg"); + EXPECT_EQ(mojom_app->readiness, apps::mojom::Readiness::kReady); + EXPECT_EQ(mojom_app->name, "lacros test name"); + EXPECT_EQ(mojom_app->short_name, "lacros test name"); + EXPECT_EQ(mojom_app->publisher_id, "publisher_id"); + EXPECT_EQ(mojom_app->description, "description"); + EXPECT_EQ(mojom_app->version, "version"); + EXPECT_EQ(mojom_app->additional_search_terms, input->additional_search_terms); + + EXPECT_EQ(mojom_app->icon_key->timeline, 1U); + EXPECT_EQ(mojom_app->icon_key->icon_effects, 2U); + + EXPECT_EQ(mojom_app->last_launch_time, base::Time() + base::Days(1)); + EXPECT_EQ(mojom_app->install_time, base::Time() + base::Days(2)); + + EXPECT_EQ(mojom_app->install_reason, apps::mojom::InstallReason::kUser); + EXPECT_EQ(mojom_app->policy_id, "https://app.site/alpha"); + EXPECT_EQ(mojom_app->recommendable, apps::mojom::OptionalBool::kTrue); + EXPECT_EQ(mojom_app->searchable, apps::mojom::OptionalBool::kTrue); + EXPECT_EQ(mojom_app->paused, apps::mojom::OptionalBool::kFalse); + EXPECT_EQ(mojom_app->show_in_launcher, apps::mojom::OptionalBool::kTrue); + EXPECT_EQ(mojom_app->show_in_shelf, apps::mojom::OptionalBool::kTrue); + EXPECT_EQ(mojom_app->show_in_search, apps::mojom::OptionalBool::kTrue); + EXPECT_EQ(mojom_app->show_in_management, apps::mojom::OptionalBool::kTrue); + EXPECT_EQ(mojom_app->has_badge, apps::mojom::OptionalBool::kUnknown); + EXPECT_EQ(mojom_app->paused, apps::mojom::OptionalBool::kFalse); + + ASSERT_EQ(mojom_app->intent_filters.size(), 1U); + auto& mojom_filter = mojom_app->intent_filters[0]; + ASSERT_EQ(mojom_filter->conditions.size(), 1U); + auto& mojom_condition = mojom_filter->conditions[0]; + EXPECT_EQ(mojom_condition->condition_type, + apps::mojom::ConditionType::kScheme); + ASSERT_EQ(mojom_condition->condition_values.size(), 1U); + EXPECT_EQ(mojom_condition->condition_values[0]->value, "https"); + EXPECT_EQ(mojom_condition->condition_values[0]->match_type, + apps::mojom::PatternMatchType::kNone); + EXPECT_EQ(mojom_filter->activity_name, "activity_name"); + EXPECT_EQ(mojom_filter->activity_label, "activity_label"); + + EXPECT_EQ(mojom_app->window_mode, apps::mojom::WindowMode::kWindow); + + ASSERT_EQ(mojom_app->permissions.size(), 1U); + auto& mojom_permission = mojom_app->permissions[0]; + EXPECT_EQ(mojom_permission->permission_type, + apps::mojom::PermissionType::kCamera); + ASSERT_TRUE(mojom_permission->value->is_bool_value()); + EXPECT_TRUE(mojom_permission->value->get_bool_value()); + EXPECT_TRUE(mojom_permission->is_managed); + + EXPECT_EQ(mojom_app->allow_uninstall, apps::mojom::OptionalBool::kTrue); + EXPECT_EQ(mojom_app->handles_intents, apps::mojom::OptionalBool::kTrue); +}
diff --git a/components/services/app_service/public/cpp/intent_filter.cc b/components/services/app_service/public/cpp/intent_filter.cc index 1444862f..c58fbbac 100644 --- a/components/services/app_service/public/cpp/intent_filter.cc +++ b/components/services/app_service/public/cpp/intent_filter.cc
@@ -119,6 +119,24 @@ } } +apps::mojom::ConditionType ConvertConditionTypeToMojomConditionType( + const ConditionType& condition_type) { + switch (condition_type) { + case ConditionType::kScheme: + return apps::mojom::ConditionType::kScheme; + case ConditionType::kHost: + return apps::mojom::ConditionType::kHost; + case ConditionType::kPattern: + return apps::mojom::ConditionType::kPattern; + case ConditionType::kAction: + return apps::mojom::ConditionType::kAction; + case ConditionType::kMimeType: + return apps::mojom::ConditionType::kMimeType; + case ConditionType::kFile: + return apps::mojom::ConditionType::kFile; + } +} + PatternMatchType ConvertMojomPatternMatchTypeToPatternMatchType( const apps::mojom::PatternMatchType& mojom_pattern_match_type) { switch (mojom_pattern_match_type) { @@ -139,6 +157,26 @@ } } +apps::mojom::PatternMatchType ConvertPatternMatchTypeToMojomPatternMatchType( + const PatternMatchType& pattern_match_type) { + switch (pattern_match_type) { + case PatternMatchType::kNone: + return apps::mojom::PatternMatchType::kNone; + case PatternMatchType::kLiteral: + return apps::mojom::PatternMatchType::kLiteral; + case PatternMatchType::kPrefix: + return apps::mojom::PatternMatchType::kPrefix; + case PatternMatchType::kGlob: + return apps::mojom::PatternMatchType::kGlob; + case PatternMatchType::kMimeType: + return apps::mojom::PatternMatchType::kMimeType; + case PatternMatchType::kFileExtension: + return apps::mojom::PatternMatchType::kFileExtension; + case PatternMatchType::kIsDirectory: + return apps::mojom::PatternMatchType::kIsDirectory; + } +} + ConditionValuePtr ConvertMojomConditionValueToConditionValue( const apps::mojom::ConditionValuePtr& mojom_condition_value) { if (!mojom_condition_value) { @@ -152,6 +190,20 @@ return condition_value; } +apps::mojom::ConditionValuePtr ConvertConditionValueToMojomConditionValue( + const ConditionValuePtr& condition_value) { + auto mojom_condition_value = apps::mojom::ConditionValue::New(); + if (!condition_value) { + return mojom_condition_value; + } + + mojom_condition_value->value = condition_value->value; + mojom_condition_value->match_type = + ConvertPatternMatchTypeToMojomPatternMatchType( + condition_value->match_type); + return mojom_condition_value; +} + ConditionPtr ConvertMojomConditionToCondition( const apps::mojom::ConditionPtr& mojom_condition) { if (!mojom_condition) { @@ -168,6 +220,25 @@ std::move(values)); } +apps::mojom::ConditionPtr ConvertConditionToMojomCondition( + const ConditionPtr& condition) { + auto mojom_condition = apps::mojom::Condition::New(); + if (!condition) { + return mojom_condition; + } + + mojom_condition->condition_type = + ConvertConditionTypeToMojomConditionType(condition->condition_type); + + for (const auto& condition_value : condition->condition_values) { + if (condition_value) { + mojom_condition->condition_values.push_back( + ConvertConditionValueToMojomConditionValue(condition_value)); + } + } + return mojom_condition; +} + IntentFilterPtr ConvertMojomIntentFilterToIntentFilter( const apps::mojom::IntentFilterPtr& mojom_intent_filter) { if (!mojom_intent_filter) { @@ -176,8 +247,10 @@ IntentFilterPtr intent_filter = std::make_unique<IntentFilter>(); for (const auto& condition : mojom_intent_filter->conditions) { - intent_filter->conditions.push_back( - ConvertMojomConditionToCondition(condition)); + if (condition) { + intent_filter->conditions.push_back( + ConvertMojomConditionToCondition(condition)); + } } if (mojom_intent_filter->activity_name.has_value()) @@ -189,4 +262,57 @@ return intent_filter; } +apps::mojom::IntentFilterPtr ConvertIntentFilterToMojomIntentFilter( + const IntentFilterPtr& intent_filter) { + auto mojom_intent_filter = apps::mojom::IntentFilter::New(); + if (!intent_filter) { + return mojom_intent_filter; + } + + for (const auto& condition : intent_filter->conditions) { + if (condition) { + mojom_intent_filter->conditions.push_back( + ConvertConditionToMojomCondition(condition)); + } + } + + mojom_intent_filter->activity_name = intent_filter->activity_name; + mojom_intent_filter->activity_label = intent_filter->activity_label; + return mojom_intent_filter; +} + +base::flat_map<std::string, std::vector<apps::mojom::IntentFilterPtr>> +ConvertIntentFiltersToMojomIntentFilters( + const base::flat_map<std::string, apps::IntentFilters>& intent_filter) { + base::flat_map<std::string, std::vector<apps::mojom::IntentFilterPtr>> ret; + for (const auto& it : intent_filter) { + std::vector<apps::mojom::IntentFilterPtr> mojom_filters; + for (const auto& filter_it : it.second) { + if (filter_it) { + mojom_filters.push_back( + ConvertIntentFilterToMojomIntentFilter(filter_it)); + } + } + ret[it.first] = std::move(mojom_filters); + } + return ret; +} + +base::flat_map<std::string, apps::IntentFilters> +ConvertMojomIntentFiltersToIntentFilters( + const base::flat_map<std::string, + std::vector<apps::mojom::IntentFilterPtr>>& + mojom_intent_filter) { + base::flat_map<std::string, apps::IntentFilters> ret; + for (const auto& it : mojom_intent_filter) { + apps::IntentFilters filters; + for (const auto& filter_it : it.second) { + if (filter_it) + filters.push_back(ConvertMojomIntentFilterToIntentFilter(filter_it)); + } + ret[it.first] = std::move(filters); + } + return ret; +} + } // namespace apps
diff --git a/components/services/app_service/public/cpp/intent_filter.h b/components/services/app_service/public/cpp/intent_filter.h index e02f1b6..7b1ba9b 100644 --- a/components/services/app_service/public/cpp/intent_filter.h +++ b/components/services/app_service/public/cpp/intent_filter.h
@@ -10,6 +10,7 @@ #include <vector> #include "base/component_export.h" +#include "base/containers/flat_map.h" #include "components/services/app_service/public/mojom/types.mojom.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -114,21 +115,53 @@ const apps::mojom::ConditionType& mojom_condition_type); COMPONENT_EXPORT(APP_TYPES) +apps::mojom::ConditionType ConvertConditionTypeToMojomConditionType( + const ConditionType& condition_type); + +COMPONENT_EXPORT(APP_TYPES) PatternMatchType ConvertMojomPatternMatchTypeToPatternMatchType( const apps::mojom::PatternMatchType& mojom_pattern_match_type); COMPONENT_EXPORT(APP_TYPES) +apps::mojom::PatternMatchType ConvertPatternMatchTypeToMojomPatternMatchType( + const PatternMatchType& pattern_match_type); + +COMPONENT_EXPORT(APP_TYPES) ConditionValuePtr ConvertMojomConditionValueToConditionValue( const apps::mojom::ConditionValuePtr& mojom_condition_value); COMPONENT_EXPORT(APP_TYPES) +apps::mojom::ConditionValuePtr ConvertConditionValueToMojomConditionValue( + const ConditionValuePtr& condition_value); + +COMPONENT_EXPORT(APP_TYPES) ConditionPtr ConvertMojomConditionToCondition( const apps::mojom::ConditionPtr& mojom_condition); COMPONENT_EXPORT(APP_TYPES) +apps::mojom::ConditionPtr ConvertConditionToMojomCondition( + const ConditionPtr& condition); + +COMPONENT_EXPORT(APP_TYPES) IntentFilterPtr ConvertMojomIntentFilterToIntentFilter( const apps::mojom::IntentFilterPtr& mojom_intent_filter); +COMPONENT_EXPORT(APP_TYPES) +apps::mojom::IntentFilterPtr ConvertIntentFilterToMojomIntentFilter( + const IntentFilterPtr& intent_filter); + +COMPONENT_EXPORT(APP_TYPES) +base::flat_map<std::string, std::vector<apps::mojom::IntentFilterPtr>> +ConvertIntentFiltersToMojomIntentFilters( + const base::flat_map<std::string, apps::IntentFilters>& intent_filter); + +COMPONENT_EXPORT(APP_TYPES) +base::flat_map<std::string, apps::IntentFilters> +ConvertMojomIntentFiltersToIntentFilters( + const base::flat_map<std::string, + std::vector<apps::mojom::IntentFilterPtr>>& + mojom_intent_filter); + } // namespace apps #endif // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_INTENT_FILTER_H_
diff --git a/components/services/app_service/public/cpp/intent_filter_util.cc b/components/services/app_service/public/cpp/intent_filter_util.cc index ca849f6..811cb6f 100644 --- a/components/services/app_service/public/cpp/intent_filter_util.cc +++ b/components/services/app_service/public/cpp/intent_filter_util.cc
@@ -84,6 +84,17 @@ return condition; } +void AddSingleValueCondition(apps::ConditionType condition_type, + const std::string& value, + apps::PatternMatchType pattern_match_type, + apps::IntentFilterPtr& intent_filter) { + apps::ConditionValues condition_values; + condition_values.push_back( + std::make_unique<apps::ConditionValue>(value, pattern_match_type)); + intent_filter->conditions.push_back(std::make_unique<apps::Condition>( + condition_type, std::move(condition_values))); +} + void AddSingleValueCondition(apps::mojom::ConditionType condition_type, const std::string& value, apps::mojom::PatternMatchType pattern_match_type,
diff --git a/components/services/app_service/public/cpp/intent_filter_util.h b/components/services/app_service/public/cpp/intent_filter_util.h index 8624079f..e4ec595 100644 --- a/components/services/app_service/public/cpp/intent_filter_util.h +++ b/components/services/app_service/public/cpp/intent_filter_util.h
@@ -9,6 +9,7 @@ #include <string> +#include "components/services/app_service/public/cpp/intent_filter.h" #include "components/services/app_service/public/mojom/types.mojom.h" #include "url/gurl.h" @@ -47,6 +48,12 @@ // Creates condition that only contain one value and add the condition to // the intent filter. +void AddSingleValueCondition(apps::ConditionType condition_type, + const std::string& value, + apps::PatternMatchType pattern_match_type, + apps::IntentFilterPtr& intent_filter); + +// TODO(crbug.com/1253250): Remove after migrating to non-mojo AppService. void AddSingleValueCondition(apps::mojom::ConditionType condition_type, const std::string& value, apps::mojom::PatternMatchType pattern_match_type,
diff --git a/components/services/app_service/public/cpp/intent_filter_util_unittest.cc b/components/services/app_service/public/cpp/intent_filter_util_unittest.cc index 190ad7d..bb6e114 100644 --- a/components/services/app_service/public/cpp/intent_filter_util_unittest.cc +++ b/components/services/app_service/public/cpp/intent_filter_util_unittest.cc
@@ -5,6 +5,7 @@ #include "components/services/app_service/public/cpp/intent_filter_util.h" #include "base/values.h" +#include "components/services/app_service/public/cpp/intent_filter.h" #include "components/services/app_service/public/cpp/intent_test_util.h" #include "components/services/app_service/public/cpp/intent_util.h" #include "testing/gtest/include/gtest/gtest.h" @@ -370,3 +371,108 @@ ASSERT_FALSE(apps_util::FiltersHaveOverlap(literal_pattern_filter2, glob_pattern_filter)); } + +TEST_F(IntentFilterUtilTest, IntentFiltersConvert) { + base::flat_map<std::string, std::vector<apps::IntentFilterPtr>> filters; + + auto intent_filter1 = std::make_unique<apps::IntentFilter>(); + apps_util::AddSingleValueCondition(apps::ConditionType::kScheme, "1", + apps::PatternMatchType::kNone, + intent_filter1); + filters["1"].push_back(std::move(intent_filter1)); + + auto intent_filter2 = std::make_unique<apps::IntentFilter>(); + apps_util::AddSingleValueCondition(apps::ConditionType::kHost, "2", + apps::PatternMatchType::kLiteral, + intent_filter2); + apps_util::AddSingleValueCondition(apps::ConditionType::kPattern, "3", + apps::PatternMatchType::kPrefix, + intent_filter2); + filters["1"].push_back(std::move(intent_filter2)); + + apps::IntentFilters intent_filters2; + auto intent_filter3 = std::make_unique<apps::IntentFilter>(); + apps_util::AddSingleValueCondition(apps::ConditionType::kAction, "4", + apps::PatternMatchType::kGlob, + intent_filter3); + apps_util::AddSingleValueCondition(apps::ConditionType::kMimeType, "5", + apps::PatternMatchType::kMimeType, + intent_filter3); + filters["2"].push_back(std::move(intent_filter3)); + + auto intent_filter4 = std::make_unique<apps::IntentFilter>(); + apps_util::AddSingleValueCondition(apps::ConditionType::kFile, "6", + apps::PatternMatchType::kMimeType, + intent_filter4); + apps_util::AddSingleValueCondition(apps::ConditionType::kFile, "7", + apps::PatternMatchType::kFileExtension, + intent_filter4); + filters["2"].push_back(std::move(intent_filter4)); + + auto output = apps::ConvertMojomIntentFiltersToIntentFilters( + apps::ConvertIntentFiltersToMojomIntentFilters(filters)); + + ASSERT_EQ(output.size(), 2U); + EXPECT_EQ(*filters["1"][0], *output["1"][0]); + EXPECT_EQ(*filters["1"][1], *output["1"][1]); + + EXPECT_EQ(*filters["2"][0], *output["2"][0]); + EXPECT_EQ(*filters["2"][1], *output["2"][1]); + + { + auto& condition = output["1"][0]->conditions[0]; + EXPECT_EQ(condition->condition_type, apps::ConditionType::kScheme); + ASSERT_EQ(condition->condition_values.size(), 1U); + EXPECT_EQ(condition->condition_values[0]->match_type, + apps::PatternMatchType::kNone); + EXPECT_EQ(condition->condition_values[0]->value, "1"); + } + { + auto& condition = output["1"][1]->conditions[0]; + EXPECT_EQ(condition->condition_type, apps::ConditionType::kHost); + ASSERT_EQ(condition->condition_values.size(), 1U); + EXPECT_EQ(condition->condition_values[0]->match_type, + apps::PatternMatchType::kLiteral); + EXPECT_EQ(condition->condition_values[0]->value, "2"); + } + { + auto& condition = output["1"][1]->conditions[1]; + EXPECT_EQ(condition->condition_type, apps::ConditionType::kPattern); + ASSERT_EQ(condition->condition_values.size(), 1U); + EXPECT_EQ(condition->condition_values[0]->match_type, + apps::PatternMatchType::kPrefix); + EXPECT_EQ(condition->condition_values[0]->value, "3"); + } + { + auto& condition = output["2"][0]->conditions[0]; + EXPECT_EQ(condition->condition_type, apps::ConditionType::kAction); + ASSERT_EQ(condition->condition_values.size(), 1U); + EXPECT_EQ(condition->condition_values[0]->match_type, + apps::PatternMatchType::kGlob); + EXPECT_EQ(condition->condition_values[0]->value, "4"); + } + { + auto& condition = output["2"][0]->conditions[1]; + EXPECT_EQ(condition->condition_type, apps::ConditionType::kMimeType); + ASSERT_EQ(condition->condition_values.size(), 1U); + EXPECT_EQ(condition->condition_values[0]->match_type, + apps::PatternMatchType::kMimeType); + EXPECT_EQ(condition->condition_values[0]->value, "5"); + } + { + auto& condition = output["2"][1]->conditions[0]; + EXPECT_EQ(condition->condition_type, apps::ConditionType::kFile); + ASSERT_EQ(condition->condition_values.size(), 1U); + EXPECT_EQ(condition->condition_values[0]->match_type, + apps::PatternMatchType::kMimeType); + EXPECT_EQ(condition->condition_values[0]->value, "6"); + } + { + auto& condition = output["2"][1]->conditions[1]; + EXPECT_EQ(condition->condition_type, apps::ConditionType::kFile); + ASSERT_EQ(condition->condition_values.size(), 1U); + EXPECT_EQ(condition->condition_values[0]->match_type, + apps::PatternMatchType::kFileExtension); + EXPECT_EQ(condition->condition_values[0]->value, "7"); + } +}
diff --git a/components/services/app_service/public/cpp/permission.cc b/components/services/app_service/public/cpp/permission.cc index c098788..7e91f5a 100644 --- a/components/services/app_service/public/cpp/permission.cc +++ b/components/services/app_service/public/cpp/permission.cc
@@ -104,6 +104,28 @@ } } +apps::mojom::PermissionType ConvertPermissionTypeToMojomPermissionType( + PermissionType permission_type) { + switch (permission_type) { + case PermissionType::kUnknown: + return apps::mojom::PermissionType::kUnknown; + case PermissionType::kCamera: + return apps::mojom::PermissionType::kCamera; + case PermissionType::kLocation: + return apps::mojom::PermissionType::kLocation; + case PermissionType::kMicrophone: + return apps::mojom::PermissionType::kMicrophone; + case PermissionType::kNotifications: + return apps::mojom::PermissionType::kNotifications; + case PermissionType::kContacts: + return apps::mojom::PermissionType::kContacts; + case PermissionType::kStorage: + return apps::mojom::PermissionType::kStorage; + case PermissionType::kPrinting: + return apps::mojom::PermissionType::kPrinting; + } +} + TriState ConvertMojomTriStateToTriState(apps::mojom::TriState mojom_tri_state) { switch (mojom_tri_state) { case apps::mojom::TriState::kAllow: @@ -115,6 +137,17 @@ } } +apps::mojom::TriState ConvertTriStateToMojomTriState(TriState tri_state) { + switch (tri_state) { + case TriState::kAllow: + return apps::mojom::TriState::kAllow; + case TriState::kBlock: + return apps::mojom::TriState::kBlock; + case TriState::kAsk: + return apps::mojom::TriState::kAsk; + } +} + PermissionValuePtr ConvertMojomPermissionValueToPermissionValue( const apps::mojom::PermissionValuePtr& mojom_permission_value) { if (!mojom_permission_value) { @@ -131,6 +164,24 @@ return nullptr; } +apps::mojom::PermissionValuePtr ConvertPermissionValueToMojomPermissionValue( + const PermissionValuePtr& permission_value) { + auto mojom_permission_value = apps::mojom::PermissionValue::New(); + if (!permission_value) { + return mojom_permission_value; + } + + if (permission_value->bool_value.has_value()) { + mojom_permission_value->set_bool_value( + permission_value->bool_value.value()); + } + if (permission_value->tristate_value.has_value()) { + mojom_permission_value->set_tristate_value(ConvertTriStateToMojomTriState( + permission_value->tristate_value.value())); + } + return mojom_permission_value; +} + PermissionPtr ConvertMojomPermissionToPermission( const apps::mojom::PermissionPtr& mojom_permission) { if (!mojom_permission) { @@ -144,4 +195,19 @@ mojom_permission->is_managed); } +apps::mojom::PermissionPtr ConvertPermissionToMojomPermission( + const PermissionPtr& permission) { + auto mojom_permission = apps::mojom::Permission::New(); + if (!permission) { + return mojom_permission; + } + + mojom_permission->permission_type = + ConvertPermissionTypeToMojomPermissionType(permission->permission_type); + mojom_permission->value = + ConvertPermissionValueToMojomPermissionValue(permission->value); + mojom_permission->is_managed = permission->is_managed; + return mojom_permission; +} + } // namespace apps
diff --git a/components/services/app_service/public/cpp/permission.h b/components/services/app_service/public/cpp/permission.h index 2f82bd76..1483cf5 100644 --- a/components/services/app_service/public/cpp/permission.h +++ b/components/services/app_service/public/cpp/permission.h
@@ -87,16 +87,31 @@ apps::mojom::PermissionType mojom_permission_type); COMPONENT_EXPORT(APP_TYPES) +apps::mojom::PermissionType ConvertPermissionTypeToMojomPermissionType( + PermissionType permission_type); + +COMPONENT_EXPORT(APP_TYPES) TriState ConvertMojomTriStateToTriState(apps::mojom::TriState mojom_tri_state); COMPONENT_EXPORT(APP_TYPES) +apps::mojom::TriState ConvertTriStateToMojomTriState(TriState tri_state); + +COMPONENT_EXPORT(APP_TYPES) PermissionValuePtr ConvertMojomPermissionValueToPermissionValue( const apps::mojom::PermissionValuePtr& mojom_permission_value); COMPONENT_EXPORT(APP_TYPES) +apps::mojom::PermissionValuePtr ConvertPermissionValueToMojomPermissionValue( + const PermissionValuePtr& permission_value); + +COMPONENT_EXPORT(APP_TYPES) PermissionPtr ConvertMojomPermissionToPermission( const apps::mojom::PermissionPtr& mojom_permission); +COMPONENT_EXPORT(APP_TYPES) +apps::mojom::PermissionPtr ConvertPermissionToMojomPermission( + const PermissionPtr& permission); + } // namespace apps #endif // COMPONENTS_SERVICES_APP_SERVICE_PUBLIC_CPP_PERMISSION_H_
diff --git a/components/services/unzip/BUILD.gn b/components/services/unzip/BUILD.gn index d2648aec..a21e47ca 100644 --- a/components/services/unzip/BUILD.gn +++ b/components/services/unzip/BUILD.gn
@@ -11,6 +11,7 @@ deps = [ "//base", "//mojo/public/cpp/bindings", + "//third_party/ced", "//third_party/zlib/google:zip", ] @@ -45,6 +46,21 @@ visibility = [ ":unit_tests" ] testonly = true sources = [ + "//components/test/data/unzip_service/SJIS 00.zip", + "//components/test/data/unzip_service/SJIS 01.zip", + "//components/test/data/unzip_service/SJIS 02.zip", + "//components/test/data/unzip_service/SJIS 03.zip", + "//components/test/data/unzip_service/SJIS 04.zip", + "//components/test/data/unzip_service/SJIS 05.zip", + "//components/test/data/unzip_service/SJIS 06.zip", + "//components/test/data/unzip_service/SJIS 07.zip", + "//components/test/data/unzip_service/SJIS 08.zip", + "//components/test/data/unzip_service/SJIS 09.zip", + "//components/test/data/unzip_service/SJIS 10.zip", + "//components/test/data/unzip_service/SJIS 11.zip", + "//components/test/data/unzip_service/SJIS 12.zip", + "//components/test/data/unzip_service/SJIS 13.zip", + "//components/test/data/unzip_service/UTF8 (Bug 903664).zip", "//components/test/data/unzip_service/bad_archive.zip", "//components/test/data/unzip_service/good_archive.zip", ]
diff --git a/components/services/unzip/DEPS b/components/services/unzip/DEPS index c182c3c..c84c5757b 100644 --- a/components/services/unzip/DEPS +++ b/components/services/unzip/DEPS
@@ -1,5 +1,6 @@ include_rules = [ "+components/services/filesystem", "+mojo/public", + "+third_party/ced", "+third_party/zlib/google", ]
diff --git a/components/services/unzip/public/cpp/unzip.cc b/components/services/unzip/public/cpp/unzip.cc index b2b929c..8b9a3be 100644 --- a/components/services/unzip/public/cpp/unzip.cc +++ b/components/services/unzip/public/cpp/unzip.cc
@@ -94,6 +94,45 @@ scoped_refptr<base::SequencedTaskRunner> background_task_runner_keep_alive_; }; +class DetectEncodingParams : public base::RefCounted<DetectEncodingParams> { + public: + DetectEncodingParams( + mojo::PendingRemote<mojom::Unzipper> unzipper, + DetectEncodingCallback callback, + scoped_refptr<base::SequencedTaskRunner> callback_task_runner, + scoped_refptr<base::SequencedTaskRunner> background_task_runner) + : unzipper_(std::move(unzipper)), + callback_(std::move(callback)), + callback_task_runner_(std::move(callback_task_runner)), + background_task_runner_(std::move(background_task_runner)) {} + + DetectEncodingParams(const DetectEncodingParams&) = delete; + DetectEncodingParams& operator=(const DetectEncodingParams&) = delete; + + mojo::Remote<mojom::Unzipper>& unzipper() { return unzipper_; } + + void InvokeCallback(int encoding) { + if (callback_) { + callback_task_runner_->PostTask( + FROM_HERE, base::BindOnce(std::move(callback_), + static_cast<Encoding>(encoding))); + } + + unzipper_.reset(); + } + + private: + friend class base::RefCounted<DetectEncodingParams>; + + ~DetectEncodingParams() = default; + + // The Remote is stored so it does not get deleted before the callback runs. + mojo::Remote<mojom::Unzipper> unzipper_; + DetectEncodingCallback callback_; + scoped_refptr<base::SequencedTaskRunner> callback_task_runner_; + scoped_refptr<base::SequencedTaskRunner> background_task_runner_; +}; + void UnzipDone(scoped_refptr<UnzipParams> params, bool success) { params->InvokeCallback(success); params->unzipper().reset(); @@ -147,6 +186,37 @@ std::move(unzip_filter_remote), base::BindOnce(&UnzipDone, unzip_params)); } +void DoDetectEncoding( + mojo::PendingRemote<mojom::Unzipper> unzipper, + const base::FilePath& zip_path, + DetectEncodingCallback result_callback, + scoped_refptr<base::SequencedTaskRunner> callback_task_runner, + scoped_refptr<base::SequencedTaskRunner> background_task_runner) { + base::File zip_file(zip_path, base::File::FLAG_OPEN | base::File::FLAG_READ); + if (!zip_file.IsValid()) { + LOG(ERROR) << "Cannot open ZIP archive '" << zip_path + << "': " << base::File::ErrorToString(zip_file.error_details()); + callback_task_runner->PostTask( + FROM_HERE, + base::BindOnce(std::move(result_callback), UNKNOWN_ENCODING)); + return; + } + + // |result_callback| is shared between the connection error handler and the + // DetectEncoding call using a refcounted DetectEncodingParams object that + // owns |result_callback|. + auto params = base::MakeRefCounted<DetectEncodingParams>( + std::move(unzipper), std::move(result_callback), + std::move(callback_task_runner), std::move(background_task_runner)); + + params->unzipper().set_disconnect_handler(base::BindOnce( + &DetectEncodingParams::InvokeCallback, params, UNKNOWN_ENCODING)); + + params->unzipper()->DetectEncoding( + std::move(zip_file), + base::BindOnce(&DetectEncodingParams::InvokeCallback, params)); +} + } // namespace void Unzip(mojo::PendingRemote<mojom::Unzipper> unzipper, @@ -176,4 +246,18 @@ background_task_runner)); } +void DetectEncoding(mojo::PendingRemote<mojom::Unzipper> unzipper, + const base::FilePath& zip_path, + DetectEncodingCallback result_callback) { + scoped_refptr<base::SequencedTaskRunner> background_task_runner = + base::ThreadPool::CreateSequencedTaskRunner( + {base::TaskPriority::USER_VISIBLE, base::MayBlock(), + base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN}); + background_task_runner->PostTask( + FROM_HERE, base::BindOnce(&DoDetectEncoding, std::move(unzipper), + zip_path, std::move(result_callback), + base::SequencedTaskRunnerHandle::Get(), + background_task_runner)); +} + } // namespace unzip
diff --git a/components/services/unzip/public/cpp/unzip.h b/components/services/unzip/public/cpp/unzip.h index e62a4ac52..1f4bbb0f 100644 --- a/components/services/unzip/public/cpp/unzip.h +++ b/components/services/unzip/public/cpp/unzip.h
@@ -8,6 +8,7 @@ #include "base/callback_forward.h" #include "components/services/unzip/public/mojom/unzipper.mojom.h" #include "mojo/public/cpp/bindings/pending_remote.h" +#include "third_party/ced/src/util/encodings/encodings.h" namespace base { class FilePath; @@ -32,6 +33,11 @@ UnzipFilterCallback filter_callback, UnzipCallback result_callback); +using DetectEncodingCallback = base::OnceCallback<void(Encoding)>; +void DetectEncoding(mojo::PendingRemote<mojom::Unzipper> unzipper, + const base::FilePath& zip_file, + DetectEncodingCallback result_callback); + } // namespace unzip #endif // COMPONENTS_SERVICES_UNZIP_PUBLIC_CPP_UNZIP_H_
diff --git a/components/services/unzip/public/cpp/unzip_unittest.cc b/components/services/unzip/public/cpp/unzip_unittest.cc index ccb90532..aad82c2 100644 --- a/components/services/unzip/public/cpp/unzip_unittest.cc +++ b/components/services/unzip/public/cpp/unzip_unittest.cc
@@ -4,33 +4,33 @@ #include "components/services/unzip/public/cpp/unzip.h" +#include <utility> + #include "base/base_paths.h" -#include "base/bind.h" #include "base/files/file_enumerator.h" #include "base/files/file_path.h" #include "base/files/file_util.h" #include "base/files/scoped_temp_dir.h" #include "base/path_service.h" #include "base/run_loop.h" +#include "base/test/bind.h" #include "base/test/task_environment.h" #include "components/services/unzip/unzipper_impl.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "testing/gtest/include/gtest/gtest.h" namespace unzip { - namespace { -// Note: this method has to return void for the ASSERTION_* to compile. -void GetArchivePath(const base::FilePath::StringPieceType& archive_name, - base::FilePath* path) { - ASSERT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, path)); - *path = path->Append(FILE_PATH_LITERAL("components")) - .Append(FILE_PATH_LITERAL("test")) - .Append(FILE_PATH_LITERAL("data")) - .Append(FILE_PATH_LITERAL("unzip_service")) - .Append(archive_name); - ASSERT_TRUE(base::PathExists(*path)); +base::FilePath GetArchivePath( + const base::FilePath::StringPieceType archive_name) { + base::FilePath path; + EXPECT_TRUE(base::PathService::Get(base::DIR_SOURCE_ROOT, &path)); + return path.Append(FILE_PATH_LITERAL("components")) + .Append(FILE_PATH_LITERAL("test")) + .Append(FILE_PATH_LITERAL("data")) + .Append(FILE_PATH_LITERAL("unzip_service")) + .Append(archive_name); } // Sets the number of files under |dir| in |file_count| and if @@ -63,29 +63,22 @@ ~UnzipTest() override = default; // Unzips |zip_file| into |output_dir| and returns true if the unzip was - // successful. + // successful. Only extract files for which |filter_callback| returns true, if + // it is provided. bool DoUnzip(const base::FilePath& zip_file, - const base::FilePath& output_dir) { - return DoUnzipWithFilter(zip_file, output_dir, UnzipFilterCallback()); - } - - // Same as DoUnzip() but only extract files for which |filter_callback| - // returns true. - bool DoUnzipWithFilter(const base::FilePath& zip_file, - const base::FilePath& output_dir, - UnzipFilterCallback filter_callback) { + const base::FilePath& output_dir, + UnzipFilterCallback filter_callback = {}) { mojo::PendingRemote<mojom::Unzipper> unzipper; receivers_.Add(&unzipper_, unzipper.InitWithNewPipeAndPassReceiver()); base::RunLoop run_loop; bool result = false; - UnzipCallback result_callback = base::BindOnce( - [](base::OnceClosure quit_closure, bool* out_result, bool result) { - *out_result = result; - std::move(quit_closure).Run(); - }, - run_loop.QuitClosure(), &result); + UnzipCallback result_callback = + base::BindLambdaForTesting([&](const bool success) { + result = success; + run_loop.QuitClosure().Run(); + }); if (filter_callback) { UnzipWithFilter(std::move(unzipper), zip_file, output_dir, @@ -98,6 +91,24 @@ return result; } + Encoding DoDetectEncoding(const base::FilePath& zip_file) { + mojo::PendingRemote<mojom::Unzipper> unzipper; + receivers_.Add(&unzipper_, unzipper.InitWithNewPipeAndPassReceiver()); + + base::RunLoop run_loop; + Encoding result = UNKNOWN_ENCODING; + + DetectEncodingCallback result_callback = + base::BindLambdaForTesting([&](const Encoding encoding) { + result = encoding; + run_loop.QuitClosure().Run(); + }); + + DetectEncoding(std::move(unzipper), zip_file, std::move(result_callback)); + run_loop.Run(); + return result; + } + protected: void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); @@ -114,9 +125,8 @@ }; TEST_F(UnzipTest, UnzipBadArchive) { - base::FilePath bad_archive; - GetArchivePath(FILE_PATH_LITERAL("bad_archive.zip"), &bad_archive); - EXPECT_FALSE(DoUnzip(bad_archive, unzip_dir_)); + EXPECT_FALSE(DoUnzip(GetArchivePath(FILE_PATH_LITERAL("bad_archive.zip")), + unzip_dir_)); // No files should have been extracted. int64_t file_count = -1; @@ -125,9 +135,8 @@ } TEST_F(UnzipTest, UnzipGoodArchive) { - base::FilePath archive; - GetArchivePath(FILE_PATH_LITERAL("good_archive.zip"), &archive); - EXPECT_TRUE(DoUnzip(archive, unzip_dir_)); + EXPECT_TRUE(DoUnzip(GetArchivePath(FILE_PATH_LITERAL("good_archive.zip")), + unzip_dir_)); // Sanity check that the right number of files have been extracted and that // they are not empty. @@ -139,13 +148,11 @@ } TEST_F(UnzipTest, UnzipWithFilter) { - base::FilePath archive; - GetArchivePath(FILE_PATH_LITERAL("good_archive.zip"), &archive); - EXPECT_TRUE(DoUnzipWithFilter( - archive, unzip_dir_, - base::BindRepeating([](const base::FilePath& path) -> bool { - return path.MatchesExtension(FILE_PATH_LITERAL(".txt")); - }))); + EXPECT_TRUE(DoUnzip(GetArchivePath(FILE_PATH_LITERAL("good_archive.zip")), + unzip_dir_, + base::BindRepeating([](const base::FilePath& path) { + return path.MatchesExtension(FILE_PATH_LITERAL(".txt")); + }))); // It should only have kept the 2 text files from the archive. int64_t file_count = -1; @@ -155,5 +162,51 @@ EXPECT_FALSE(some_files_empty); } +TEST_F(UnzipTest, DetectEncodingAbsentArchive) { + EXPECT_EQ(UNKNOWN_ENCODING, DoDetectEncoding(GetArchivePath( + FILE_PATH_LITERAL("absent_archive.zip")))); +} + +TEST_F(UnzipTest, DetectEncodingBadArchive) { + EXPECT_EQ( + UNKNOWN_ENCODING, + DoDetectEncoding(GetArchivePath(FILE_PATH_LITERAL("bad_archive.zip")))); +} + +TEST_F(UnzipTest, DetectEncodingAscii) { + EXPECT_EQ( + Encoding::ASCII_7BIT, + DoDetectEncoding(GetArchivePath(FILE_PATH_LITERAL("good_archive.zip")))); +} + +// See https://crbug.com/903664 +TEST_F(UnzipTest, DetectEncodingUtf8) { + EXPECT_EQ(Encoding::UTF8, DoDetectEncoding(GetArchivePath( + FILE_PATH_LITERAL("UTF8 (Bug 903664).zip")))); +} + +// See https://crbug.com/1287893 +TEST_F(UnzipTest, DetectEncodingSjis) { + for (const base::FilePath::StringPieceType name : { + FILE_PATH_LITERAL("SJIS 00.zip"), + FILE_PATH_LITERAL("SJIS 01.zip"), + FILE_PATH_LITERAL("SJIS 02.zip"), + FILE_PATH_LITERAL("SJIS 03.zip"), + FILE_PATH_LITERAL("SJIS 04.zip"), + FILE_PATH_LITERAL("SJIS 05.zip"), + FILE_PATH_LITERAL("SJIS 06.zip"), + FILE_PATH_LITERAL("SJIS 07.zip"), + FILE_PATH_LITERAL("SJIS 08.zip"), + FILE_PATH_LITERAL("SJIS 09.zip"), + FILE_PATH_LITERAL("SJIS 10.zip"), + FILE_PATH_LITERAL("SJIS 11.zip"), + FILE_PATH_LITERAL("SJIS 12.zip"), + FILE_PATH_LITERAL("SJIS 13.zip"), + }) { + EXPECT_EQ(Encoding::JAPANESE_SHIFT_JIS, + DoDetectEncoding(GetArchivePath(name))); + } +} + } // namespace } // namespace unzip
diff --git a/components/services/unzip/public/mojom/unzipper.mojom b/components/services/unzip/public/mojom/unzipper.mojom index 00273934..c6bbc40f 100644 --- a/components/services/unzip/public/mojom/unzipper.mojom +++ b/components/services/unzip/public/mojom/unzipper.mojom
@@ -30,4 +30,10 @@ mojo_base.mojom.ReadOnlyFile zip_file, pending_remote<filesystem.mojom.Directory> output_dir, pending_remote<UnzipFilter> filter) => (bool result); + + // Detects the encoding of filenames stored in the ZIP archive. + // Returns an Encoding as defined in + // third_party/ced/src/util/encodings/encodings.pb.h + // or UNKNOWN_ENCODING in case of error. + DetectEncoding(mojo_base.mojom.ReadOnlyFile zip_file) => (int32 encoding); };
diff --git a/components/services/unzip/unzipper_impl.cc b/components/services/unzip/unzipper_impl.cc index 52d3e2c..2af478a 100644 --- a/components/services/unzip/unzipper_impl.cc +++ b/components/services/unzip/unzipper_impl.cc
@@ -9,10 +9,13 @@ #include "base/bind.h" #include "base/compiler_specific.h" +#include "base/files/file.h" +#include "base/logging.h" #include "base/strings/utf_string_conversions.h" #include "build/build_config.h" #include "components/services/filesystem/public/mojom/directory.mojom.h" #include "mojo/public/cpp/bindings/remote.h" +#include "third_party/ced/src/compact_enc_det/compact_enc_det.h" #include "third_party/zlib/google/zip.h" #include "third_party/zlib/google/zip_reader.h" @@ -97,6 +100,45 @@ return result; } +// Reads the given ZIP archive, and returns all the filenames concatenated +// together in one long string capped at ~100KB, without any separator, and in +// the encoding used by the ZIP archive itself. Returns an empty string if the +// ZIP cannot be read. +std::string GetRawFileNamesFromZip(const base::File& zip_file) { + std::string result; + + // Open ZIP archive for reading. + zip::ZipReader reader; + if (!reader.OpenFromPlatformFile(zip_file.GetPlatformFile())) { + LOG(ERROR) << "Cannot decode ZIP archive"; + return result; + } + + // Reserve a ~100KB buffer. + result.reserve(100000); + + // Iterate over file entries of the ZIP archive. + while (reader.HasMore()) { + if (reader.OpenCurrentEntryInZip()) { + const std::string& entry_path = + reader.current_entry_info()->file_path_in_original_encoding(); + + // Stop if we have enough data in |result|. + if (entry_path.size() > (result.capacity() - result.size())) + break; + + // Accumulate data in |result|. + result += entry_path; + } + + if (!reader.AdvanceToNextEntry()) + break; + } + + LOG_IF(ERROR, result.empty()) << "Cannot extract filenames from ZIP archive"; + return result; +} + } // namespace UnzipperImpl::UnzipperImpl() = default; @@ -143,4 +185,35 @@ /*log_skipped_files=*/false)); } +void UnzipperImpl::DetectEncoding(base::File zip_file, + DetectEncodingCallback callback) { + DCHECK(zip_file.IsValid()); + + // Accumulate raw filenames. + const std::string all_names = GetRawFileNamesFromZip(zip_file); + if (all_names.empty()) { + std::move(callback).Run(UNKNOWN_ENCODING); + return; + } + + // Detect encoding. + int consumed_bytes = 0; + bool is_reliable = false; + const Encoding encoding = CompactEncDet::DetectEncoding( + all_names.data(), all_names.size(), nullptr, nullptr, nullptr, + UNKNOWN_ENCODING, UNKNOWN_LANGUAGE, + CompactEncDet::QUERY_CORPUS, // Plain text + true, // Exclude 7-bit encodings + &consumed_bytes, &is_reliable); + + VLOG(1) << "Detected encoding: " << MimeEncodingName(encoding) << " (" + << encoding << "), reliable: " << is_reliable + << ", consumed bytes: " << consumed_bytes; + + LOG_IF(ERROR, encoding == UNKNOWN_ENCODING) + << "Cannot detect encoding of filenames in ZIP archive"; + + std::move(callback).Run(encoding); +} + } // namespace unzip
diff --git a/components/services/unzip/unzipper_impl.h b/components/services/unzip/unzipper_impl.h index 330b716f..65d3d05 100644 --- a/components/services/unzip/unzipper_impl.h +++ b/components/services/unzip/unzipper_impl.h
@@ -40,6 +40,9 @@ mojo::PendingRemote<mojom::UnzipFilter> filter_remote, UnzipWithFilterCallback callback) override; + void DetectEncoding(base::File zip_file, + DetectEncodingCallback callback) override; + mojo::Receiver<mojom::Unzipper> receiver_{this}; };
diff --git a/components/shared_highlighting/core/common/shared_highlighting_metrics.h b/components/shared_highlighting/core/common/shared_highlighting_metrics.h index 6701441..24e9864 100644 --- a/components/shared_highlighting/core/common/shared_highlighting_metrics.h +++ b/components/shared_highlighting/core/common/shared_highlighting_metrics.h
@@ -97,8 +97,9 @@ kOmniboxNavigation = 3, kTabCrash = 4, kTimeout = 5, + kEmptySelector = 6, - kMaxValue = kTimeout, + kMaxValue = kEmptySelector, }; // Records the type of link generation that was copied on desktop.
diff --git a/components/subresource_filter/content/browser/ads_intervention_manager.cc b/components/subresource_filter/content/browser/ads_intervention_manager.cc index edf220c..8c5fcff 100644 --- a/components/subresource_filter/content/browser/ads_intervention_manager.cc +++ b/components/subresource_filter/content/browser/ads_intervention_manager.cc
@@ -92,17 +92,16 @@ if (!dict) return absl::nullopt; - int ads_violation; + absl::optional<int> ads_violation = dict->FindIntKey(kLastAdsViolationKey); absl::optional<double> last_violation_time = dict->FindDoubleKey(kLastAdsViolationTimeKey); - if (dict->GetInteger(kLastAdsViolationKey, &ads_violation) && - last_violation_time) { + if (ads_violation && last_violation_time) { base::TimeDelta diff = clock_->Now() - base::Time::FromDoubleT(*last_violation_time); return LastAdsIntervention( - {diff, static_cast<mojom::AdsViolation>(ads_violation)}); + {diff, static_cast<mojom::AdsViolation>(*ads_violation)}); } return absl::nullopt;
diff --git a/components/test/data/unzip_service/SJIS 00.zip b/components/test/data/unzip_service/SJIS 00.zip new file mode 100644 index 0000000..b185ed7 --- /dev/null +++ b/components/test/data/unzip_service/SJIS 00.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 01.zip b/components/test/data/unzip_service/SJIS 01.zip new file mode 100644 index 0000000..c977a75 --- /dev/null +++ b/components/test/data/unzip_service/SJIS 01.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 02.zip b/components/test/data/unzip_service/SJIS 02.zip new file mode 100644 index 0000000..42398ab --- /dev/null +++ b/components/test/data/unzip_service/SJIS 02.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 03.zip b/components/test/data/unzip_service/SJIS 03.zip new file mode 100644 index 0000000..b7f5ecb --- /dev/null +++ b/components/test/data/unzip_service/SJIS 03.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 04.zip b/components/test/data/unzip_service/SJIS 04.zip new file mode 100644 index 0000000..90f7197 --- /dev/null +++ b/components/test/data/unzip_service/SJIS 04.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 05.zip b/components/test/data/unzip_service/SJIS 05.zip new file mode 100644 index 0000000..8c257633 --- /dev/null +++ b/components/test/data/unzip_service/SJIS 05.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 06.zip b/components/test/data/unzip_service/SJIS 06.zip new file mode 100644 index 0000000..ceb04a0 --- /dev/null +++ b/components/test/data/unzip_service/SJIS 06.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 07.zip b/components/test/data/unzip_service/SJIS 07.zip new file mode 100644 index 0000000..ff94a5e3 --- /dev/null +++ b/components/test/data/unzip_service/SJIS 07.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 08.zip b/components/test/data/unzip_service/SJIS 08.zip new file mode 100644 index 0000000..8ef545db --- /dev/null +++ b/components/test/data/unzip_service/SJIS 08.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 09.zip b/components/test/data/unzip_service/SJIS 09.zip new file mode 100644 index 0000000..af21b17 --- /dev/null +++ b/components/test/data/unzip_service/SJIS 09.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 10.zip b/components/test/data/unzip_service/SJIS 10.zip new file mode 100644 index 0000000..be7e746 --- /dev/null +++ b/components/test/data/unzip_service/SJIS 10.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 11.zip b/components/test/data/unzip_service/SJIS 11.zip new file mode 100644 index 0000000..ca58552 --- /dev/null +++ b/components/test/data/unzip_service/SJIS 11.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 12.zip b/components/test/data/unzip_service/SJIS 12.zip new file mode 100644 index 0000000..ec68b25 --- /dev/null +++ b/components/test/data/unzip_service/SJIS 12.zip Binary files differ
diff --git a/components/test/data/unzip_service/SJIS 13.zip b/components/test/data/unzip_service/SJIS 13.zip new file mode 100644 index 0000000..fb7f131 --- /dev/null +++ b/components/test/data/unzip_service/SJIS 13.zip Binary files differ
diff --git "a/components/test/data/unzip_service/UTF8 \050Bug 903664\051.zip" "b/components/test/data/unzip_service/UTF8 \050Bug 903664\051.zip" new file mode 100644 index 0000000..4ca811a3 --- /dev/null +++ "b/components/test/data/unzip_service/UTF8 \050Bug 903664\051.zip" Binary files differ
diff --git a/components/tracing/common/trace_startup_config.cc b/components/tracing/common/trace_startup_config.cc index 7ce7c8c..0bca91b 100644 --- a/components/tracing/common/trace_startup_config.cc +++ b/components/tracing/common/trace_startup_config.cc
@@ -305,8 +305,8 @@ trace_config_ = base::trace_event::TraceConfig(*trace_config_dict); - if (!dict->GetInteger(kStartupDurationParam, &startup_duration_in_seconds_)) - startup_duration_in_seconds_ = 0; + startup_duration_in_seconds_ = + dict->FindIntKey(kStartupDurationParam).value_or(0); if (startup_duration_in_seconds_ < 0) startup_duration_in_seconds_ = 0;
diff --git a/components/ukm/ukm_recorder_impl.cc b/components/ukm/ukm_recorder_impl.cc index d555224..e8b13bc 100644 --- a/components/ukm/ukm_recorder_impl.cc +++ b/components/ukm/ukm_recorder_impl.cc
@@ -49,6 +49,11 @@ type == SourceIdType::NO_URL_ID; } +bool IsAppIdType(SourceId source_id) { + SourceIdType type = GetSourceIdType(source_id); + return type == SourceIdType::APP_ID; +} + // Returns whether |url| has one of the schemes supported for logging to UKM. // URLs with other schemes will not be logged. bool HasSupportedScheme(const GURL& url) { @@ -525,7 +530,38 @@ } } + // Special case APP_IDs. Ideally this is not going to exist for too long, as + // it would be preferable to have a more general purpose solution. + std::set<SourceId> source_ids_app_id; + + // Only done if we are in the experiment that will leave APP_ID metrics for + // last when pruning. This block extracts out all source_ids from the + // seen/unseen lists and stores them in |source_ids_app_id|. + if (base::GetFieldTrialParamByFeatureAsBool(kUkmFeature, "PruneAppIdLast", + false)) { + it = source_ids_seen.begin(); + while (it != source_ids_seen.end()) { + if (IsAppIdType(*it)) { + source_ids_app_id.insert(*it); + it = source_ids_seen.erase(it); + } else { + it++; + } + } + + it = source_ids_unseen.begin(); + while (it != source_ids_unseen.end()) { + if (IsAppIdType(*it)) { + source_ids_app_id.insert(*it); + it = source_ids_unseen.erase(it); + } else { + it++; + } + } + } + int pruned_sources_age_sec = 0; + int num_sources = recordings_.sources.size(); // Setup an experiment to test what will occur if we prune unseen sources // first. if (base::GetFieldTrialParamByFeatureAsBool( @@ -533,15 +569,39 @@ int pruned_sources_age_from_unseen_sec = PruneOldSources(max_kept_sources_, source_ids_unseen); + UMA_HISTOGRAM_COUNTS_10000("UKM.PrunedSources.NumUnseen", + num_sources - recordings_.sources.size()); + num_sources = recordings_.sources.size(); + // Prune again from seen sources. Note that if we've already pruned enough // from the unseen sources, this will be a noop. int pruned_sources_age_from_seen_sec = PruneOldSources(max_kept_sources_, source_ids_seen); + UMA_HISTOGRAM_COUNTS_10000("UKM.PrunedSources.NumSeen", + num_sources - recordings_.sources.size()); + num_sources = recordings_.sources.size(); + + int pruned_sources_age_from_app_id_sec = 0; + + // Technically this should be fine without the feature, since the group + // will be empty, but might as well add the feature check. + // Still prune the APP_ID entries. We don't want it to be unbounded, but + // providing a higher default here in case. + if (base::GetFieldTrialParamByFeatureAsBool(kUkmFeature, "PruneAppIdLast", + false)) { + pruned_sources_age_from_app_id_sec = + PruneOldSources(500, source_ids_app_id); + + UMA_HISTOGRAM_COUNTS_10000("UKM.PrunedSources.NumAppId", + num_sources - recordings_.sources.size()); + } + // We're looking for the newest age, which will be the largest between the // two sets we pruned from. - pruned_sources_age_sec = std::max(pruned_sources_age_from_unseen_sec, - pruned_sources_age_from_seen_sec); + pruned_sources_age_sec = std::max({pruned_sources_age_from_unseen_sec, + pruned_sources_age_from_seen_sec, + pruned_sources_age_from_app_id_sec}); } else { // In this case, we prune all sources without caring if they were seen or @@ -551,8 +611,39 @@ for (const auto& kv : recordings_.sources) { all_sources.insert(kv.first); } + if (base::GetFieldTrialParamByFeatureAsBool(kUkmFeature, "PruneAppIdLast", + false)) { + std::set<SourceId> all_sources_without_app_id; - pruned_sources_age_sec = PruneOldSources(max_kept_sources_, all_sources); + // This will put into |all_sources_without_app_id| the set of + // |all_sources| - |source_ids_app_id|. + std::set_difference(all_sources.begin(), all_sources.end(), + source_ids_app_id.begin(), source_ids_app_id.end(), + std::inserter(all_sources_without_app_id, + all_sources_without_app_id.end())); + + // Now, prune the non-APP_ID, then the APP_ID. + int pruned_sources_age_sec_non_app_id = + PruneOldSources(max_kept_sources_, all_sources_without_app_id); + + UMA_HISTOGRAM_COUNTS_10000("UKM.PrunedSources.AppExpNumNonAppId", + num_sources - recordings_.sources.size()); + num_sources = recordings_.sources.size(); + + int pruned_sources_age_sec_app_id = + PruneOldSources(500, source_ids_app_id); + + UMA_HISTOGRAM_COUNTS_10000("UKM.PrunedSources.AppExpNumAppId", + num_sources - recordings_.sources.size()); + + pruned_sources_age_sec = std::max(pruned_sources_age_sec_non_app_id, + pruned_sources_age_sec_app_id); + + } else { + pruned_sources_age_sec = PruneOldSources(max_kept_sources_, all_sources); + UMA_HISTOGRAM_COUNTS_10000("UKM.PrunedSources.NoExp", + num_sources - recordings_.sources.size()); + } } // Record how old the newest truncated source is.
diff --git a/components/ukm/ukm_service_unittest.cc b/components/ukm/ukm_service_unittest.cc index b95fcec..79b57320 100644 --- a/components/ukm/ukm_service_unittest.cc +++ b/components/ukm/ukm_service_unittest.cc
@@ -186,6 +186,10 @@ return ConvertToSourceId(id, SourceIdType::NAVIGATION_ID); } + static SourceId GetAppIDSourceId(int64_t id) { + return ConvertToSourceId(id, SourceIdType::APP_ID); + } + static SourceId GetNonWhitelistedSourceId(int64_t id) { return ConvertToSourceId(id, SourceIdType::DEFAULT); } @@ -1691,4 +1695,101 @@ } } +TEST_F(UkmServiceTest, PruneAppIDLast) { + // We will be testing with the PruneAppIdLast feature both off and on. + for (bool prune_app_id_last : {true, false}) { + const GURL kURL("https://google.com/foobar"); + + // Set the 'MaxKeptSources' value to 3 so it is easier to test. + ScopedUkmFeatureParams params( + {{"MaxKeptSources", "3"}, + {"PruneAppIdLast", prune_app_id_last ? "true" : "false"}}); + + ClearPrefs(); + UkmService service(&prefs_, &client_, + std::make_unique<MockDemographicMetricsProvider>()); + TestRecordingHelper recorder(&service); + EXPECT_EQ(0, GetPersistedLogCount()); + service.Initialize(); + task_runner_->RunUntilIdle(); + service.EnableRecording(/*extensions=*/false); + service.EnableReporting(); + + // Create 5 sources. We set source 0 and 4 to be APP_ID Sources, where + // 1,2,3 are whitelisted/navigation sources. + std::vector<SourceId> ids; + base::TimeTicks last_time = base::TimeTicks::Now(); + for (int i = 0; i < 5; ++i) { + // Wait until base::TimeTicks::Now() no longer equals |last_time|. This + // ensures each source has a unique timestamp to avoid flakes. Should take + // between 1-15ms per documented resolution of base::TimeTicks. + while (base::TimeTicks::Now() == last_time) { + base::PlatformThread::Sleep(base::Milliseconds(1)); + } + // Note, this is where we are setting the source types. Important for the + // testing. + if (i == 0 || i == 4) { + ids.push_back(GetAppIDSourceId(i)); + } else { + ids.push_back(GetWhitelistedSourceId(i)); + } + recorder.UpdateSourceURL(ids.back(), kURL); + last_time = base::TimeTicks::Now(); + } + + service.Flush(); + EXPECT_EQ(1, GetPersistedLogCount()); + auto proto_report = GetPersistedReport(); + + EXPECT_EQ(5, proto_report.source_counts().observed()); + + // In all cases, 3 will be deferred since that is our max allowed. + EXPECT_EQ(3, proto_report.source_counts().deferred_sources()); + // This is from last time, so none there. + EXPECT_EQ(0, proto_report.source_counts().carryover_sources()); + + // All 5 sources will be included in this first report. + ASSERT_EQ(5, proto_report.sources_size()); + EXPECT_EQ(ids[0], proto_report.sources(0).id()); + EXPECT_EQ(ids[1], proto_report.sources(1).id()); + EXPECT_EQ(ids[2], proto_report.sources(2).id()); + EXPECT_EQ(ids[3], proto_report.sources(3).id()); + EXPECT_EQ(ids[4], proto_report.sources(4).id()); + + // We have MaxKeptSources=3. + // If PruneAppIdLast was set, then the ones kept should be the two that were + // set as APP_ID, which are 0 and 4. The one remaining one will be picked + // via age which will be 3, so 0, 3, 4 are kept. + // Otherwise, it will be entirely based on age, which is 2,3,4. + + service.Flush(); + EXPECT_EQ(2, GetPersistedLogCount()); + proto_report = GetPersistedReport(); + + // No new sources observed. + EXPECT_EQ(0, proto_report.source_counts().observed()); + // 0 again, as this is for newly observed ones. + EXPECT_EQ(0, proto_report.source_counts().unmatched_sources()); + + // Since no new sources added, we still are keeping the same 3. So all 3 are + // kept and retained, in both cases. + EXPECT_EQ(3, proto_report.source_counts().deferred_sources()); + EXPECT_EQ(3, proto_report.source_counts().carryover_sources()); + ASSERT_EQ(3, proto_report.sources_size()); + + if (prune_app_id_last) { + // 0, 3, 4 as 0 and 4 are APP_ID, and 3 is the newest of the remaining. + EXPECT_EQ(ids[0], proto_report.sources(0).id()); + EXPECT_EQ(ids[3], proto_report.sources(1).id()); + EXPECT_EQ(ids[4], proto_report.sources(2).id()); + } else { + // 2, 3, 4 as these are the 3 newest, which is the only criteria we are + // using for this test. + EXPECT_EQ(ids[2], proto_report.sources(0).id()); + EXPECT_EQ(ids[3], proto_report.sources(1).id()); + EXPECT_EQ(ids[4], proto_report.sources(2).id()); + } + } +} + } // namespace ukm
diff --git a/components/user_manager/known_user.cc b/components/user_manager/known_user.cc index f1a1eff..05b5fa5e 100644 --- a/components/user_manager/known_user.cc +++ b/components/user_manager/known_user.cc
@@ -1038,15 +1038,5 @@ return KnownUser(local_state).SetAccountManager(account_id, manager); } -void SetUserLastLoginInputMethodId(const AccountId& account_id, - const std::string& input_method_id) { - PrefService* local_state = GetLocalStateLegacy(); - // Local State may not be initialized in tests. - if (!local_state) - return; - return KnownUser(local_state) - .SetUserLastLoginInputMethodId(account_id, input_method_id); -} - } // namespace known_user } // namespace user_manager
diff --git a/components/user_manager/known_user.h b/components/user_manager/known_user.h index d4ae20a8..a80b64c 100644 --- a/components/user_manager/known_user.h +++ b/components/user_manager/known_user.h
@@ -417,11 +417,6 @@ // instead. void USER_MANAGER_EXPORT SetAccountManager(const AccountId& account_id, const std::string& manager); -// TODO(https://crbug.com/1150434): Deprecated, use -// KnownUser::SetUserLastLoginInputMethodId instead. -void USER_MANAGER_EXPORT -SetUserLastLoginInputMethodId(const AccountId& account_id, - const std::string& input_method_id); } // namespace known_user } // namespace user_manager
diff --git a/components/viz/service/display_embedder/output_presenter.cc b/components/viz/service/display_embedder/output_presenter.cc index 9f696373..0d9abbe5 100644 --- a/components/viz/service/display_embedder/output_presenter.cc +++ b/components/viz/service/display_embedder/output_presenter.cc
@@ -119,7 +119,8 @@ return nullptr; } -void OutputPresenter::ScheduleBackground(Image* image) { +void OutputPresenter::ScheduleOneOverlay(const OverlayCandidate& overlay, + ScopedOverlayAccess* access) { NOTREACHED(); }
diff --git a/components/viz/service/display_embedder/output_presenter.h b/components/viz/service/display_embedder/output_presenter.h index f7314a2..6585a84 100644 --- a/components/viz/service/display_embedder/output_presenter.h +++ b/components/viz/service/display_embedder/output_presenter.h
@@ -108,9 +108,10 @@ bool is_submitted) = 0; using ScopedOverlayAccess = gpu::SharedImageRepresentationOverlay::ScopedReadAccess; + virtual void ScheduleOneOverlay(const OverlayCandidate& overlay, + ScopedOverlayAccess* access); virtual void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays, std::vector<ScopedOverlayAccess*> accesses) = 0; - virtual void ScheduleBackground(Image* image); #if BUILDFLAG(IS_MAC) virtual void SetCALayerErrorCode(gfx::CALayerResult ca_layer_error_code) {} #endif
diff --git a/components/viz/service/display_embedder/output_presenter_gl.cc b/components/viz/service/display_embedder/output_presenter_gl.cc index e463967..e9f9217f 100644 --- a/components/viz/service/display_embedder/output_presenter_gl.cc +++ b/components/viz/service/display_embedder/output_presenter_gl.cc
@@ -9,6 +9,7 @@ #include <vector> #include "base/feature_list.h" +#include "base/notreached.h" #include "base/threading/thread_task_runner_handle.h" #include "build/build_config.h" #include "components/viz/common/features.h" @@ -369,26 +370,24 @@ /*hdr_metadata=*/absl::nullopt)); } -void OutputPresenterGL::ScheduleBackground(Image* image) { - auto* presenter_image = static_cast<PresenterImageGL*>(image); - // Background is not seen by user, and is created before buffer queue buffers. - // So fence is not needed. - auto* gl_image = presenter_image->GetGLImage(nullptr); - - // Background is also z-order 0. - constexpr int kPlaneZOrder = INT32_MIN; - // Background always uses the full texture. - constexpr gfx::RectF kUVRect(0.f, 0.f, 1.0f, 1.0f); - gl_surface_->ScheduleOverlayPlane( - gl_image, /*gpu_fence=*/nullptr, - gfx::OverlayPlaneData(kPlaneZOrder, gfx::OVERLAY_TRANSFORM_NONE, - gfx::RectF(), - /*crop_rect=*/kUVRect, - /*enable_blend=*/false, /*damage_rect=*/gfx::Rect(), - /*opacity=*/1.0f, gfx::OverlayPriorityHint::kNone, - /*rounded_corners=*/gfx::RRectF(), - /*color_space=*/presenter_image->color_space(), - /*hdr_metadata=*/absl::nullopt)); +void OutputPresenterGL::ScheduleOneOverlay(const OverlayCandidate& overlay, + ScopedOverlayAccess* access) { +#if BUILDFLAG(IS_ANDROID) || defined(USE_OZONE) + auto* gl_image = access ? access->gl_image() : nullptr; + if (gl_image || overlay.solid_color.has_value()) { + DCHECK(!overlay.gpu_fence_id); + gl_surface_->ScheduleOverlayPlane( + gl_image, access ? TakeGpuFence(access->TakeAcquireFences()) : nullptr, + gfx::OverlayPlaneData( + overlay.plane_z_order, overlay.transform, overlay.display_rect, + overlay.uv_rect, !overlay.is_opaque, + ToEnclosingRect(overlay.damage_rect), overlay.opacity, + overlay.priority_hint, overlay.rounded_corners, overlay.color_space, + overlay.hdr_metadata, overlay.solid_color)); + } +#else // BUILDFLAG(IS_ANDROID) || defined(USE_OZONE) + NOTREACHED(); +#endif // BUILDFLAG(IS_ANDROID) || defined(USE_OZONE) } void OutputPresenterGL::CommitOverlayPlanes(
diff --git a/components/viz/service/display_embedder/output_presenter_gl.h b/components/viz/service/display_embedder/output_presenter_gl.h index 0c10b221fc..0ab10a4 100644 --- a/components/viz/service/display_embedder/output_presenter_gl.h +++ b/components/viz/service/display_embedder/output_presenter_gl.h
@@ -65,9 +65,10 @@ const OverlayProcessorInterface::OutputSurfaceOverlayPlane& plane, Image* image, bool is_submitted) final; + void ScheduleOneOverlay(const OverlayCandidate& overlay, + ScopedOverlayAccess* access) final; void ScheduleOverlays(SkiaOutputSurface::OverlayList overlays, std::vector<ScopedOverlayAccess*> accesses) final; - void ScheduleBackground(Image* image) final; #if BUILDFLAG(IS_MAC) void SetCALayerErrorCode(gfx::CALayerResult ca_layer_error_code) final;
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc index f872edb..16939a4 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.cc
@@ -14,8 +14,10 @@ #include "base/compiler_specific.h" #include "base/containers/cxx20_erase.h" #include "base/debug/alias.h" +#include "base/notreached.h" #include "build/build_config.h" #include "components/viz/common/switches.h" +#include "components/viz/service/display/overlay_candidate.h" #include "components/viz/service/display_embedder/skia_output_surface_dependency.h" #include "gpu/command_buffer/common/capabilities.h" #include "gpu/command_buffer/service/feature_info.h" @@ -24,8 +26,10 @@ #include "gpu/command_buffer/service/shared_image_representation.h" #include "gpu/config/gpu_finch_features.h" #include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkColor.h" #include "third_party/skia/include/core/SkSurface.h" #include "third_party/skia/include/core/SkSurfaceProps.h" +#include "ui/gfx/geometry/rect_f.h" #include "ui/gfx/swap_result.h" #include "ui/gl/gl_surface.h" @@ -41,11 +45,6 @@ } g_last_reshape_failure = now; } - -// See |needs_background_image| for details. -constexpr size_t kNumberOfBackgroundImages = 2u; -constexpr gfx::Size kBackgroundImageSize(4, 4); - } // namespace namespace viz { @@ -254,7 +253,8 @@ const absl::optional<OverlayProcessorInterface::OutputSurfaceOverlayPlane>& plane) { // See |needs_background_image|. - MaybeScheduleBackgroundImage(); + MaybeScheduleBackgroundImage(plane.has_value() ? plane->display_rect + : gfx::RectF{4.f, 4.f}); if (plane) { // If the current_image_ is nullptr, it means there is no change on the @@ -330,8 +330,62 @@ image_mailbox, std::make_pair(color, std::move(solid_color)))); return image_mailbox; } - #endif + +SkiaOutputDeviceBufferQueue::OverlayData* +SkiaOutputDeviceBufferQueue::GetOrCreateOverlayData( + const gpu::Mailbox& mailbox) { + if (!mailbox.IsSharedImage()) + return nullptr; + + auto it = overlays_.find(mailbox); + if (it != overlays_.end()) { + // If the overlay is in |overlays_|, we will reuse it, and a ref will be + // added to keep it alive. This ref will be removed, when the overlay is + // replaced by a new frame. + it->Ref(); + return &*it; + } + + auto shared_image = representation_factory_->ProduceOverlay(mailbox); + // When display is re-opened, the first few frames might not have video + // resource ready. Possible investigation crbug.com/1023971. + if (!shared_image) { + LOG(ERROR) << "Invalid mailbox."; + return nullptr; + } + + // Fuchsia does not provide a GLImage overlay. +#if BUILDFLAG(IS_FUCHSIA) + const bool needs_gl_image = false; +#else + const bool needs_gl_image = true; +#endif // BUILDFLAG(IS_FUCHSIA) + + // TODO(penghuang): do not depend on GLImage. + auto shared_image_access = + shared_image->BeginScopedReadAccess(needs_gl_image); + if (!shared_image_access) { + LOG(ERROR) << "Could not access SharedImage for read."; + return nullptr; + } + + // TODO(penghuang): do not depend on GLImage. + DLOG_IF(FATAL, needs_gl_image && !shared_image_access->gl_image()) + << "Cannot get GLImage."; + + bool result; + std::tie(it, result) = overlays_.emplace(std::move(shared_image), + std::move(shared_image_access)); + DCHECK(result); + DCHECK(it->unique()); + + // Add an extra ref to keep it alive. This extra ref will be removed when + // the backing is not used by system compositor anymore. + it->Ref(); + return &*it; +} + void SkiaOutputDeviceBufferQueue::ScheduleOverlays( SkiaOutputSurface::OverlayList overlays) { DCHECK(pending_overlay_mailboxes_.empty()); @@ -352,58 +406,11 @@ } #endif - if (!overlay.mailbox.IsSharedImage()) + auto* overlay_data = GetOrCreateOverlayData(overlay.mailbox); + if (!overlay_data) continue; - auto it = overlays_.find(overlay.mailbox); - if (it != overlays_.end()) { - // If the overlay is in |overlays_|, we will reuse it, and a ref will be - // added to keep it alive. This ref will be removed, when the overlay is - // replaced by a new frame. - it->Ref(); - accesses[i] = it->scoped_read_access(); - pending_overlay_mailboxes_.emplace_back(overlay.mailbox); - continue; - } - - auto shared_image = - representation_factory_->ProduceOverlay(overlay.mailbox); - // When display is re-opened, the first few frames might not have video - // resource ready. Possible investigation crbug.com/1023971. - if (!shared_image) { - LOG(ERROR) << "Invalid mailbox."; - continue; - } - - // Fuchsia does not provide a GLImage overlay. -#if BUILDFLAG(IS_FUCHSIA) - const bool needs_gl_image = false; -#else - const bool needs_gl_image = true; -#endif // BUILDFLAG(IS_FUCHSIA) - - // TODO(penghuang): do not depend on GLImage. - auto shared_image_access = - shared_image->BeginScopedReadAccess(needs_gl_image); - if (!shared_image_access) { - LOG(ERROR) << "Could not access SharedImage for read."; - continue; - } - - // TODO(penghuang): do not depend on GLImage. - DLOG_IF(FATAL, needs_gl_image && !shared_image_access->gl_image()) - << "Cannot get GLImage."; - - bool result; - std::tie(it, result) = overlays_.emplace(std::move(shared_image), - std::move(shared_image_access)); - DCHECK(result); - DCHECK(it->unique()); - - // Add an extra ref to keep it alive. This extra ref will be removed when - // the backing is not used by system compositor anymore. - it->Ref(); - accesses[i] = it->scoped_read_access(); + accesses[i] = overlay_data->scoped_read_access(); pending_overlay_mailboxes_.emplace_back(overlay.mailbox); } @@ -650,9 +657,6 @@ overlay_transform_ = transform; - // See |needs_background_image|. - MaybeAllocateBackgroundImages(); - if (color_space_ == color_space && image_size_ == size) return true; color_space_ = color_space; @@ -686,38 +690,34 @@ return !images_.empty(); } -void SkiaOutputDeviceBufferQueue::MaybeAllocateBackgroundImages() { - if (!needs_background_image_ || !background_images_.empty()) - return; - - background_images_ = presenter_->AllocateImages( - color_space_, kBackgroundImageSize, kNumberOfBackgroundImages); - DCHECK(!background_images_.empty()); - - // Clear the background images to avoid undesired artifacts. - for (auto& image : background_images_) { - image->BeginWriteSkia(); - image->sk_surface()->getCanvas()->clear(SkColors::kTransparent); - image->EndWriteSkia(/*force_flush*/ true); - } -} - -void SkiaOutputDeviceBufferQueue::MaybeScheduleBackgroundImage() { +void SkiaOutputDeviceBufferQueue::MaybeScheduleBackgroundImage( + const gfx::RectF& display_rect) { if (!needs_background_image_) return; - if (current_background_image_) - current_background_image_->EndPresent({}); - current_background_image_ = GetNextBackgroundImage(); - current_background_image_->BeginPresent(); - presenter_->ScheduleBackground(current_background_image_); -} + gpu::SharedImageRepresentationOverlay::ScopedReadAccess* access = nullptr; + OverlayCandidate candidate; + candidate.color_space = color_space_; + candidate.display_rect = display_rect; + candidate.solid_color = SK_ColorTRANSPARENT; + candidate.plane_z_order = INT32_MIN; -OutputPresenter::Image* SkiaOutputDeviceBufferQueue::GetNextBackgroundImage() { - DCHECK_EQ(background_images_.size(), kNumberOfBackgroundImages); - return current_background_image_ == background_images_.front().get() - ? background_images_.back().get() - : background_images_.front().get(); +#if defined(USE_OZONE) + if (!supports_non_backed_solid_color_images_) { + auto mailbox = GetImageMailboxForColor(candidate.solid_color.value()); + DCHECK(mailbox.IsSharedImage()); + + auto* overlay_data = GetOrCreateOverlayData(mailbox); + DCHECK(overlay_data); + + access = overlay_data->scoped_read_access(); + pending_overlay_mailboxes_.emplace_back(mailbox); + } +#else // defined(USE_OZONE) + NOTREACHED(); +#endif // !defined(USE_OZONE) + + presenter_->ScheduleOneOverlay(candidate, access); } SkSurface* SkiaOutputDeviceBufferQueue::BeginPaint(
diff --git a/components/viz/service/display_embedder/skia_output_device_buffer_queue.h b/components/viz/service/display_embedder/skia_output_device_buffer_queue.h index f71805ae..ea8833e1 100644 --- a/components/viz/service/display_embedder/skia_output_device_buffer_queue.h +++ b/components/viz/service/display_embedder/skia_output_device_buffer_queue.h
@@ -90,9 +90,11 @@ gfx::Size GetSwapBuffersSize(); bool RecreateImages(); - void MaybeAllocateBackgroundImages(); - void MaybeScheduleBackgroundImage(); - OutputPresenter::Image* GetNextBackgroundImage(); + void MaybeScheduleBackgroundImage(const gfx::RectF& display_rect); + + // Given an overlay mailbox, returns the corresponding OverlayData* from + // |overlays_|. Inserts an OverlayData if mailbox is not in |overlays_|. + OverlayData* GetOrCreateOverlayData(const gpu::Mailbox& mailbox); std::unique_ptr<OutputPresenter> presenter_; @@ -154,14 +156,6 @@ // it for opaque accelerated widgets and event wiring. Please see details on // the number of background images below. bool needs_background_image_ = false; - // 4x4 small images that will be scaled to cover an opaque region. - // It's required to have two background images to be scheduled so that - // Desktop Wayland compositors are able to apply state changes to root - // surfaces. Otherwise, they unref the attached buffer after processing it - // and never update the state changes of the root surface, which leads to - // a broken resize opetion. - std::vector<std::unique_ptr<OutputPresenter::Image>> background_images_; - OutputPresenter::Image* current_background_image_ = nullptr; // Whether the platform supports non-backed solid color overlays. The Wayland // backend is able to delegate these overlays without buffer backings // depending on the availability of a certain protocol.
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.h b/content/browser/accessibility/browser_accessibility_cocoa.h index aba0e975e..31340a44 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.h +++ b/content/browser/accessibility/browser_accessibility_cocoa.h
@@ -128,8 +128,6 @@ @property(nonatomic, readonly) id disclosedByRow; @property(nonatomic, readonly) NSNumber* disclosureLevel; @property(nonatomic, readonly) id disclosedRows; -// Returns the object at the root of the current edit field, if any. -@property(nonatomic, readonly) id editableAncestor; @property(nonatomic, readonly) NSNumber* enabled; // Returns a text marker that points to the last character in the document that // can be selected with Voiceover.
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm index 0fea479..9055829 100644 --- a/content/browser/accessibility/browser_accessibility_cocoa.mm +++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
@@ -68,10 +68,6 @@ namespace { // Private WebKit accessibility attributes. -NSString* const NSAccessibilityEditableAncestorAttribute = - @"AXEditableAncestor"; -NSString* const NSAccessibilityHighestEditableAncestorAttribute = - @"AXHighestEditableAncestor"; NSString* const NSAccessibilityLoadingProgressAttribute = @"AXLoadingProgress"; NSString* const NSAccessibilityOwnsAttribute = @"AXOwns"; NSString* const @@ -627,15 +623,12 @@ {NSAccessibilityDisclosedByRowAttribute, @"disclosedByRow"}, {NSAccessibilityDisclosureLevelAttribute, @"disclosureLevel"}, {NSAccessibilityDisclosedRowsAttribute, @"disclosedRows"}, - {NSAccessibilityEditableAncestorAttribute, @"editableAncestor"}, {NSAccessibilityEnabledAttribute, @"enabled"}, {NSAccessibilityEndTextMarkerAttribute, @"endTextMarker"}, {NSAccessibilityExpandedAttribute, @"expanded"}, {NSAccessibilityFocusedAttribute, @"focused"}, {NSAccessibilityHeaderAttribute, @"header"}, {NSAccessibilityHelpAttribute, @"help"}, - {NSAccessibilityHighestEditableAncestorAttribute, - @"highestEditableAncestor"}, {NSAccessibilityIndexAttribute, @"index"}, {NSAccessibilityInsertionPointLineNumberAttribute, @"insertionPointLineNumber"}, @@ -930,15 +923,6 @@ return nil; } -- (id)editableAncestor { - if (![self instanceActive]) - return nil; - auto* text_field_ancestor = - const_cast<BrowserAccessibility*>(_owner->PlatformGetTextFieldAncestor()); - return text_field_ancestor ? text_field_ancestor->GetNativeViewAccessible() - : nil; -} - - (NSNumber*)enabled { if (![self instanceActive]) return nil; @@ -1009,26 +993,6 @@ ax::mojom::StringAttribute::kDescription); } -- (id)highestEditableAncestor { - if (![self instanceActive]) - return nil; - - BrowserAccessibilityCocoa* highestEditableAncestor = [self editableAncestor]; - while (highestEditableAncestor) { - BrowserAccessibilityCocoa* ancestorParent = - [highestEditableAncestor parent]; - if (!ancestorParent || ![ancestorParent isKindOfClass:[self class]]) { - break; - } - BrowserAccessibilityCocoa* higherAncestor = - [ancestorParent editableAncestor]; - if (!higherAncestor) - break; - highestEditableAncestor = higherAncestor; - } - return highestEditableAncestor; -} - - (NSNumber*)index { if (![self instanceActive]) return nil; @@ -2879,17 +2843,6 @@ ]]; } - // Caret navigation and text selection attributes. - if (_owner->HasState(ax::mojom::State::kEditable)) { - // Add ancestor attributes if not a web area. - if (!ui::IsPlatformDocument(_owner->GetRole())) { - [ret addObjectsFromArray:@[ - NSAccessibilityEditableAncestorAttribute, - NSAccessibilityHighestEditableAncestorAttribute - ]]; - } - } - if (_owner->IsTextField()) { [ret addObjectsFromArray:@[ NSAccessibilityInsertionPointLineNumberAttribute,
diff --git a/content/browser/accessibility/browser_accessibility_manager_mac.mm b/content/browser/accessibility/browser_accessibility_manager_mac.mm index e584bb18..89964f9 100644 --- a/content/browser/accessibility/browser_accessibility_manager_mac.mm +++ b/content/browser/accessibility/browser_accessibility_manager_mac.mm
@@ -452,12 +452,15 @@ std::set<const BrowserAccessibilityCocoa*> changed_editable_roots; for (const auto& change : changes) { - BrowserAccessibility* obj = GetFromAXNode(change.node); - if (obj && obj->HasState(ax::mojom::State::kEditable)) { - const BrowserAccessibilityCocoa* editable_root = - [obj->GetNativeViewAccessible() editableAncestor]; - if (editable_root && [editable_root instanceActive]) - changed_editable_roots.insert(editable_root); + if (change.node->HasState(ax::mojom::State::kEditable)) { + auto* ancestor = change.node->GetTextFieldAncestor(); + if (ancestor) { + BrowserAccessibility* obj = GetFromAXNode(ancestor); + const BrowserAccessibilityCocoa* editable_root = + obj->GetNativeViewAccessible(); + if ([editable_root instanceActive]) + changed_editable_roots.insert(editable_root); + } } }
diff --git a/content/browser/accessibility/dump_accessibility_scripts_browsertest.cc b/content/browser/accessibility/dump_accessibility_scripts_browsertest.cc index 4e500ac..1c4e6f17 100644 --- a/content/browser/accessibility/dump_accessibility_scripts_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_scripts_browsertest.cc
@@ -214,6 +214,10 @@ RunTypedTest<kMacAttributes>("ax-dom-identifier.html"); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityScriptTest, AXEditableAncestor) { + RunTypedTest<kMacAttributes>("ax-editable-ancestor.html"); +} + IN_PROC_BROWSER_TEST_P(DumpAccessibilityScriptTest, AXDropEffects) { RunTypedTest<kMacAttributes>("ax-drop-effects.html"); } @@ -234,6 +238,10 @@ RunTypedTest<kMacAttributes>("ax-has-popup.html"); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityScriptTest, AXHighestEditableAncestor) { + RunTypedTest<kMacAttributes>("ax-highest-editable-ancestor.html"); +} + IN_PROC_BROWSER_TEST_P(DumpAccessibilityScriptTest, AXInvalid) { RunTypedTest<kMacAttributes>("ax-invalid.html"); }
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc index c17bf38..fe715197 100644 --- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc +++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
@@ -1150,6 +1150,11 @@ } IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, + AccessibilityAriaTwoOwnersRemoveOne) { + RunAriaTest(FILE_PATH_LITERAL("aria-two-owners-remove-one.html")); +} + +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AccessibilityAriaOwnsIgnored) { RunAriaTest(FILE_PATH_LITERAL("aria-owns-ignored.html")); } @@ -3213,6 +3218,10 @@ RunRegressionTest(FILE_PATH_LITERAL("remove-pseudo-content.html")); } +IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, RemoveAriaOwner) { + RunRegressionTest(FILE_PATH_LITERAL("remove-aria-owner.html")); +} + IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, ReusedMap) { RunRegressionTest(FILE_PATH_LITERAL("reused-map.html")); }
diff --git a/content/browser/android/content_feature_list.cc b/content/browser/android/content_feature_list.cc index 35e5d8fd..b6b764d 100644 --- a/content/browser/android/content_feature_list.cc +++ b/content/browser/android/content_feature_list.cc
@@ -25,6 +25,7 @@ &features::kAccessibilityPageZoom, &features::kBackgroundMediaRendererHasModerateBinding, &features::kBindingManagementWaiveCpu, + &features::kComputeAXMode, &features::kDragAndDrop, &features::kOnDemandAccessibilityEvents, &features::kProcessSharingWithStrictSiteInstances,
diff --git a/content/browser/attribution_reporting/attribution_internals_ui.cc b/content/browser/attribution_reporting/attribution_internals_ui.cc index ea26d3e..a475f882b 100644 --- a/content/browser/attribution_reporting/attribution_internals_ui.cc +++ b/content/browser/attribution_reporting/attribution_internals_ui.cc
@@ -22,8 +22,9 @@ // Initialize the UI with no bindings. Mojo bindings will be separately // granted to frames within this WebContents. web_ui->SetBindings(BINDINGS_POLICY_NONE); - WebUIDataSource* source = - WebUIDataSource::Create(kChromeUIAttributionInternalsHost); + WebUIDataSource* source = WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), + kChromeUIAttributionInternalsHost); source->AddResourcePath("attribution_internals.mojom-webui.js", IDR_ATTRIBUTION_INTERNALS_MOJOM_JS); @@ -35,7 +36,6 @@ source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::TrustedTypes, "trusted-types static-types;"); - WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), source); } WEB_UI_CONTROLLER_TYPE_IMPL(AttributionInternalsUI)
diff --git a/content/browser/attribution_reporting/attribution_manager_impl.cc b/content/browser/attribution_reporting/attribution_manager_impl.cc index 6bbcb39..fa3c0f1 100644 --- a/content/browser/attribution_reporting/attribution_manager_impl.cc +++ b/content/browser/attribution_reporting/attribution_manager_impl.cc
@@ -28,6 +28,7 @@ #include "content/browser/attribution_reporting/storable_source.h" #include "content/browser/attribution_reporting/stored_source.h" #include "content/browser/storage_partition_impl.h" +#include "content/public/browser/attribution_reporting.h" #include "content/public/browser/browser_context.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/network_service_instance.h" @@ -119,6 +120,19 @@ return content::GetNetworkConnectionTracker()->IsOffline(); } +std::unique_ptr<AttributionStorage::Delegate> MakeStorageDelegate() { + bool debug_mode = base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kConversionsDebugMode); + + if (debug_mode) { + return std::make_unique<AttributionStorageDelegateImpl>( + AttributionNoiseMode::kNone, AttributionDelayMode::kNone); + } + + return std::make_unique<AttributionStorageDelegateImpl>( + AttributionNoiseMode::kDefault, AttributionDelayMode::kDefault); +} + } // namespace AttributionManager* AttributionManagerProviderImpl::GetManager( @@ -175,9 +189,7 @@ DefaultIsReportAllowedCallback(storage_partition->browser_context()), user_data_directory, std::move(special_storage_policy), - std::make_unique<AttributionStorageDelegateImpl>( - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kConversionsDebugMode)), + MakeStorageDelegate(), std::make_unique<AttributionCookieCheckerImpl>(storage_partition), std::make_unique<AttributionNetworkSenderImpl>(storage_partition)) {}
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc b/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc index fe7b4e1..3d61af9 100644 --- a/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc +++ b/content/browser/attribution_reporting/attribution_storage_delegate_impl.cc
@@ -15,8 +15,10 @@ namespace content { -AttributionStorageDelegateImpl::AttributionStorageDelegateImpl(bool debug_mode) - : debug_mode_(debug_mode) { +AttributionStorageDelegateImpl::AttributionStorageDelegateImpl( + AttributionNoiseMode noise_mode, + AttributionDelayMode delay_mode) + : noise_mode_(noise_mode), delay_mode_(delay_mode) { DETACH_FROM_SEQUENCE(sequence_checker_); } @@ -72,10 +74,13 @@ const CommonSourceInfo& source, base::Time trigger_time) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - // If in debug mode, the report should be sent immediately. - if (debug_mode_) - return trigger_time; - return ComputeReportTime(source, trigger_time); + + switch (delay_mode_) { + case AttributionDelayMode::kDefault: + return ComputeReportTime(source, trigger_time); + case AttributionDelayMode::kNone: + return trigger_time; + } } base::GUID AttributionStorageDelegateImpl::NewReportID() const { @@ -84,24 +89,32 @@ absl::optional<AttributionStorage::Delegate::OfflineReportDelayConfig> AttributionStorageDelegateImpl::GetOfflineReportDelayConfig() const { - if (debug_mode_) - return absl::nullopt; + if (noise_mode_ == AttributionNoiseMode::kDefault && + delay_mode_ == AttributionDelayMode::kDefault) { + // Add uniform random noise in the range of [0, 1 minutes] to the report + // time. + // TODO(https://crbug.com/1075600): This delay is very conservative. + // Consider increasing this delay once we can be sure reports are still + // sent at reasonable times, and not delayed for many browser sessions due + // to short session up-times. + return OfflineReportDelayConfig{ + .min = base::Minutes(0), + .max = base::Minutes(1), + }; + } - // Add uniform random noise in the range of [0, 1 minutes] to the report time. - // TODO(https://crbug.com/1075600): This delay is very conservative. Consider - // increasing this delay once we can be sure reports are still sent at - // reasonable times, and not delayed for many browser sessions due to short - // session up-times. - return OfflineReportDelayConfig{ - .min = base::Minutes(0), - .max = base::Minutes(1), - }; + return absl::nullopt; } void AttributionStorageDelegateImpl::ShuffleReports( std::vector<AttributionReport>& reports) const { - if (!debug_mode_) - base::RandomShuffle(reports.begin(), reports.end()); + switch (noise_mode_) { + case AttributionNoiseMode::kDefault: + base::RandomShuffle(reports.begin(), reports.end()); + break; + case AttributionNoiseMode::kNone: + break; + } } AttributionStorage::Delegate::RandomizedResponse @@ -109,23 +122,27 @@ const CommonSourceInfo& source) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (debug_mode_) - return absl::nullopt; + switch (noise_mode_) { + case AttributionNoiseMode::kDefault: { + double randomized_trigger_rate = + RandomizedTriggerRate(source.source_type()); + DCHECK_GE(randomized_trigger_rate, 0); + DCHECK_LE(randomized_trigger_rate, 1); - double randomized_trigger_rate = RandomizedTriggerRate(source.source_type()); - DCHECK_GE(randomized_trigger_rate, 0); - DCHECK_LE(randomized_trigger_rate, 1); - - if (base::RandDouble() < randomized_trigger_rate) - return GetRandomFakeReports(source); - - return absl::nullopt; + return base::RandDouble() < randomized_trigger_rate + ? absl::make_optional(GetRandomFakeReports(source)) + : absl::nullopt; + } + case AttributionNoiseMode::kNone: + return absl::nullopt; + } } std::vector<AttributionStorage::Delegate::FakeReport> AttributionStorageDelegateImpl::GetRandomFakeReports( const CommonSourceInfo& source) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(noise_mode_, AttributionNoiseMode::kDefault); const int num_combinations = GetNumberOfStarsAndBarsSequences( /*num_stars=*/GetMaxAttributionsPerSource(source.source_type()), @@ -143,6 +160,7 @@ const CommonSourceInfo& source, int random_stars_and_bars_sequence_index) const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK_EQ(noise_mode_, AttributionNoiseMode::kDefault); const int trigger_data_cardinality = TriggerDataCardinality(source.source_type());
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl.h b/content/browser/attribution_reporting/attribution_storage_delegate_impl.h index e1a0d6f8..8472580 100644 --- a/content/browser/attribution_reporting/attribution_storage_delegate_impl.h +++ b/content/browser/attribution_reporting/attribution_storage_delegate_impl.h
@@ -11,6 +11,7 @@ #include "content/browser/attribution_reporting/attribution_storage.h" #include "content/browser/attribution_reporting/common_source_info.h" #include "content/common/content_export.h" +#include "content/public/browser/attribution_reporting.h" namespace base { class GUID; @@ -29,7 +30,9 @@ class CONTENT_EXPORT AttributionStorageDelegateImpl : public AttributionStorage::Delegate { public: - explicit AttributionStorageDelegateImpl(bool debug_mode = false); + explicit AttributionStorageDelegateImpl( + AttributionNoiseMode noise_mode = AttributionNoiseMode::kDefault, + AttributionDelayMode delay_mode = AttributionDelayMode::kDefault); AttributionStorageDelegateImpl(const AttributionStorageDelegateImpl& other) = delete; AttributionStorageDelegateImpl& operator=( @@ -80,9 +83,8 @@ int random_stars_and_bars_sequence_index) const; private: - // Whether the API is running in debug mode, meaning that there should be - // no delays or noise added to reports. - const bool debug_mode_; + const AttributionNoiseMode noise_mode_; + const AttributionDelayMode delay_mode_; SEQUENCE_CHECKER(sequence_checker_); };
diff --git a/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc b/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc index 38c84a0..e0fd6a3 100644 --- a/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc +++ b/content/browser/attribution_reporting/attribution_storage_delegate_impl_unittest.cc
@@ -14,6 +14,7 @@ #include "content/browser/attribution_reporting/combinatorics.h" #include "content/browser/attribution_reporting/common_source_info.h" #include "content/browser/attribution_reporting/stored_source.h" +#include "content/public/browser/attribution_reporting.h" #include "testing/gtest/include/gtest/gtest.h" namespace content { @@ -201,10 +202,10 @@ } TEST(AttributionStorageDelegateImplTest, - RandomizedResponse_DebugModeReturnsNull) { + RandomizedResponse_NoNoiseModeReturnsNull) { for (auto source_type : kSourceTypes) { EXPECT_EQ( - AttributionStorageDelegateImpl(/*debug_mode=*/true) + AttributionStorageDelegateImpl(AttributionNoiseMode::kNone) .GetRandomizedResponse( SourceBuilder().SetSourceType(source_type).BuildCommonInfo()), absl::nullopt);
diff --git a/content/browser/client_hints/client_hints.cc b/content/browser/client_hints/client_hints.cc index 422e5c32..e47aeff 100644 --- a/content/browser/client_hints/client_hints.cc +++ b/content/browser/client_hints/client_hints.cc
@@ -451,46 +451,47 @@ } // Returns true iff the `url` is embedded inside a frame that has the -// Sec-CH-UA-Reduced client hint and thus, is enrolled in the -// UserAgentReduction Origin Trial. +// corresponding Sec-CH-UA-Reduced or Sec-CH-UA-Full client hint and thus, is +// enrolled in the UserAgentReduction or SendFullUserAgentAfterReduction Origin +// Trial. // -// TODO(crbug.com/1258063): Remove when the UserAgentReduction Origin Trial is -// finished. -bool IsUserAgentReductionEnabledForEmbeddedFrame( +// TODO(crbug.com/1258063): Remove when the UserAgentReduction and +// SendFullUserAgentAfterReduction Origin Trial is finished. +bool AreUserAgentOriginTrialHintsEnabledForFrame( const GURL& url, const GURL& main_frame_url, FrameTreeNode* frame_tree_node, - ClientHintsControllerDelegate* delegate) { - bool is_embedder_ua_reduced = false; + ClientHintsControllerDelegate* delegate, + WebClientHintsType hint_type) { + bool is_embedder_in_ua_origin_trial = false; RenderFrameHostImpl* current = frame_tree_node->current_frame_host(); while (current) { const GURL& current_url = (current == frame_tree_node->current_frame_host()) ? url : current->GetLastCommittedURL(); - // Don't use Sec-CH-UA-Reduced from third-party origins if third-party - // cookies are blocked, so that we don't reveal any more user data than - // is allowed by the cookie settings. + // Don't use Sec-CH-UA-Reduced or Sec-CH-UA-Full from third-party origins if + // third-party cookies are blocked, so that we don't reveal any more user + // data than is allowed by the cookie settings. if (url::IsSameOriginWith(current_url, main_frame_url) || !delegate->AreThirdPartyCookiesBlocked(current_url)) { blink::EnabledClientHints current_url_hints; delegate->GetAllowedClientHintsFromSource(current_url, ¤t_url_hints); - if ((is_embedder_ua_reduced = - base::Contains(current_url_hints.GetEnabledHints(), - WebClientHintsType::kUAReduced))) { + if ((is_embedder_in_ua_origin_trial = base::Contains( + current_url_hints.GetEnabledHints(), hint_type))) { break; } } current = current->GetParent(); } - return is_embedder_ua_reduced; + return is_embedder_in_ua_origin_trial; } -// TODO(crbug.com/1258063): Delete this function when the UserAgentReduction -// Origin Trial is finished. -void RemoveAllClientHintsExceptUaReduced( +// TODO(crbug.com/1258063): Delete this function when the UserAgentReduction and +// SendFullUserAgentAfterReduction Origin Trial is finished. +void RemoveAllClientHintsExceptUaReducedOrUaDeprecation( const GURL& url, FrameTreeNode* frame_tree_node, ClientHintsControllerDelegate* delegate, @@ -501,7 +502,8 @@ frame_tree_node->frame_tree()->GetMainFrame(); for (auto it = accept_ch->begin(); it != accept_ch->end();) { - if (*it == WebClientHintsType::kUAReduced) { + if (*it == WebClientHintsType::kUAReduced || + *it == WebClientHintsType::kFullUserAgent) { ++it; } else { it = accept_ch->erase(it); @@ -555,8 +557,12 @@ // TODO(crbug.com/1258063): Remove once the UserAgentReduction Origin Trial // is finished. if (frame_tree_node && !is_main_frame) { - is_embedder_ua_reduced = IsUserAgentReductionEnabledForEmbeddedFrame( - url, main_frame_url, frame_tree_node, delegate); + is_embedder_ua_reduced = AreUserAgentOriginTrialHintsEnabledForFrame( + url, main_frame_url, frame_tree_node, delegate, + WebClientHintsType::kUAReduced); + is_embedder_ua_full = AreUserAgentOriginTrialHintsEnabledForFrame( + url, main_frame_url, frame_tree_node, delegate, + WebClientHintsType::kFullUserAgent); } // Record the time spent getting the client hints. @@ -573,6 +579,14 @@ // receive the reduced User-Agent header, so we want to also send the reduced // User-Agent for the embedded request as well. bool is_embedder_ua_reduced = false; + // If true, one of the ancestor requests in the path to this request had + // Sec-CH-UA-Full in their Accept-CH cache. Only applies to embedded + // requests (top-level requests will always set this to false). + // + // If an embedder of a request has Sec-CH-UA-Full, it means it will + // receive the full User-Agent header, so we want to also send the full + // User-Agent for the embedded request as well. + bool is_embedder_ua_full = false; url::Origin resource_origin; bool is_main_frame = false; GURL main_frame_url; @@ -581,17 +595,17 @@ }; bool SkipPermissionPolicyCheck(WebClientHintsType type) { - // TODO(crbug/1282230): Add || type == WebClientHintsType::kFullUserAgent; - return type == WebClientHintsType::kUAReduced; + return type == WebClientHintsType::kUAReduced || + type == WebClientHintsType::kFullUserAgent; } bool IsClientHintEnabled(const ClientHintsExtendedData& data, WebClientHintsType type) { return blink::IsClientHintSentByDefault(type) || data.hints.IsEnabled(type) || (type == WebClientHintsType::kUAReduced && - data.is_embedder_ua_reduced); - // TODO(crbug/1282230): Add || (type == WebClientHintsType::kFullUserAgent && - // data.is_embedder_ua_full); + data.is_embedder_ua_reduced) || + (type == WebClientHintsType::kFullUserAgent && + data.is_embedder_ua_full); } bool IsClientHintAllowed(const ClientHintsExtendedData& data, @@ -763,6 +777,10 @@ AddUAHeader(headers, WebClientHintsType::kUAFullVersionList, ua_metadata->SerializeBrandFullVersionList()); } + if (ShouldAddClientHint(data, WebClientHintsType::kFullUserAgent)) { + AddUAHeader(headers, WebClientHintsType::kFullUserAgent, + SerializeHeaderString(true)); + } } else if (call_type == ClientUaHeaderCallType::kAfterCreated) { RemoveClientHintHeader(WebClientHintsType::kUA, headers); RemoveClientHintHeader(WebClientHintsType::kUAMobile, headers); @@ -775,6 +793,7 @@ RemoveClientHintHeader(WebClientHintsType::kUAReduced, headers); RemoveClientHintHeader(WebClientHintsType::kUAFullVersionList, headers); RemoveClientHintHeader(WebClientHintsType::kUAWoW64, headers); + RemoveClientHintHeader(WebClientHintsType::kFullUserAgent, headers); } } @@ -989,9 +1008,9 @@ // TODO(crbug.com/1258063): Delete this call when the UserAgentReduction // Origin Trial is finished. if (!frame_tree_node->IsMainFrame()) { - RemoveAllClientHintsExceptUaReduced(url, frame_tree_node, delegate, - &accept_ch, &main_frame_url, - &third_party_url); + RemoveAllClientHintsExceptUaReducedOrUaDeprecation( + url, frame_tree_node, delegate, &accept_ch, &main_frame_url, + &third_party_url); if (accept_ch.empty()) { // There are is no Sec-CH-UA-Reduced in Accept-CH for the embedded frame, // so nothing should be persisted. @@ -1033,6 +1052,10 @@ !base::Contains(hints, WebClientHintsType::kUAReduced)) { hints.push_back(WebClientHintsType::kUAReduced); } + if (data.is_embedder_ua_full && + !base::Contains(hints, WebClientHintsType::kFullUserAgent)) { + hints.push_back(WebClientHintsType::kFullUserAgent); + } return hints; }
diff --git a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc index 7816bfb..70946a1 100644 --- a/content/browser/devtools/protocol/devtools_protocol_browsertest.cc +++ b/content/browser/devtools/protocol/devtools_protocol_browsertest.cc
@@ -936,7 +936,13 @@ WaitForNotification("Inspector.targetReloadedAfterCrash", true); } -IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsProtocolTest, PageCrashInFrame) { +#if BUILDFLAG(IS_ANDROID) +#define MAYBE_PageCrashInFrame DISABLED_PageCrashInFrame +#else +#define MAYBE_PageCrashInFrame PageCrashInFrame +#endif +IN_PROC_BROWSER_TEST_F(SitePerProcessDevToolsProtocolTest, + MAYBE_PageCrashInFrame) { ASSERT_TRUE(embedded_test_server()->Start()); GURL test_url = embedded_test_server()->GetURL("/devtools/page-with-oopif.html");
diff --git a/content/browser/indexed_db/indexed_db_internals_ui.cc b/content/browser/indexed_db/indexed_db_internals_ui.cc index a9fb626c..04b8e5bf 100644 --- a/content/browser/indexed_db/indexed_db_internals_ui.cc +++ b/content/browser/indexed_db/indexed_db_internals_ui.cc
@@ -37,8 +37,9 @@ IndexedDBInternalsUI::IndexedDBInternalsUI(WebUI* web_ui) : WebUIController(web_ui) { web_ui->AddMessageHandler(std::make_unique<IndexedDBInternalsHandler>()); - WebUIDataSource* source = - WebUIDataSource::Create(kChromeUIIndexedDBInternalsHost); + WebUIDataSource* source = WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), + kChromeUIIndexedDBInternalsHost); source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); @@ -51,10 +52,6 @@ source->AddResourcePath("indexeddb_internals.css", IDR_INDEXED_DB_INTERNALS_CSS); source->SetDefaultResource(IDR_INDEXED_DB_INTERNALS_HTML); - - BrowserContext* browser_context = - web_ui->GetWebContents()->GetBrowserContext(); - WebUIDataSource::Add(browser_context, source); } IndexedDBInternalsUI::~IndexedDBInternalsUI() = default;
diff --git a/content/browser/interest_group/auction_runner.cc b/content/browser/interest_group/auction_runner.cc index 503e17c..cc6a4cf 100644 --- a/content/browser/interest_group/auction_runner.cc +++ b/content/browser/interest_group/auction_runner.cc
@@ -101,6 +101,115 @@ AuctionRunner::ScoredBid::~ScoredBid() = default; +AuctionRunner::Auction::Auction( + blink::mojom::AuctionAdConfig* config, + AuctionWorkletManager* auction_worklet_manager, + InterestGroupManagerImpl* interest_group_manager, + base::Time auction_start_time) + : auction_worklet_manager_(auction_worklet_manager), + interest_group_manager_(interest_group_manager), + config_(config), + auction_start_time_(auction_start_time) {} + +AuctionRunner::Auction::~Auction() = default; + +void AuctionRunner::Auction::LoadInterestGroups( + IsInterestGroupApiAllowedCallback is_interest_group_api_allowed_callback, + LoadInterestGroupsCallback load_interest_groups_callback) { + DCHECK(!load_interest_groups_callback_); + DCHECK(!final_auction_result_); + DCHECK_EQ(num_pending_buyers_, 0u); + + load_interest_groups_callback_ = std::move(load_interest_groups_callback); + + // If the seller can't participate in the auction, fail the auction. + if (!is_interest_group_api_allowed_callback.Run( + ContentBrowserClient::InterestGroupApiOperation::kSell, + config_->seller)) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&Auction::OnLoadInterestGroupsComplete, + weak_ptr_factory_.GetWeakPtr(), + AuctionResult::kSellerRejected)); + return; + } + + if (config_->auction_ad_config_non_shared_params->interest_group_buyers) { + for (const auto& buyer : + *config_->auction_ad_config_non_shared_params->interest_group_buyers) { + if (!is_interest_group_api_allowed_callback.Run( + ContentBrowserClient::InterestGroupApiOperation::kBuy, buyer)) { + continue; + } + interest_group_manager_->GetInterestGroupsForOwner( + buyer, base::BindOnce(&Auction::OnInterestGroupRead, + weak_ptr_factory_.GetWeakPtr())); + ++num_pending_buyers_; + } + } + + // Fail if there are no pending loads. + if (num_pending_buyers_ == 0) { + base::SequencedTaskRunnerHandle::Get()->PostTask( + FROM_HERE, base::BindOnce(&Auction::OnLoadInterestGroupsComplete, + weak_ptr_factory_.GetWeakPtr(), + AuctionResult::kNoInterestGroups)); + } +} + +void AuctionRunner::Auction::OnInterestGroupRead( + std::vector<StorageInterestGroup> interest_groups) { + DCHECK_GT(num_pending_buyers_, 0u); + --num_pending_buyers_; + + if (!interest_groups.empty()) { + for (auto bidder = std::make_move_iterator(interest_groups.begin()); + bidder != std::make_move_iterator(interest_groups.end()); ++bidder) { + // Ignore interest groups with no bidding script or no ads. + if (!bidder->interest_group.bidding_url) + continue; + if (bidder->interest_group.ads->empty()) + continue; + bid_states_.emplace_back(BidState()); + bid_states_.back().bidder = std::move(*bidder); + } + ++num_owners_with_interest_groups_; + } + + // Wait for more buyers to be loaded, if there are still some pending. + if (num_pending_buyers_ > 0) + return; + + // Record histograms about the interest groups participating in the auction. + UMA_HISTOGRAM_COUNTS_1000("Ads.InterestGroup.Auction.NumInterestGroups", + bid_states_.size()); + UMA_HISTOGRAM_COUNTS_100( + "Ads.InterestGroup.Auction.NumOwnersWithInterestGroups", + num_owners_with_interest_groups_); + + // If there are no bidders in this auction, fail the auction. + if (bid_states_.empty()) { + OnLoadInterestGroupsComplete(AuctionResult::kNoInterestGroups); + return; + } + + // There are bidders that can generate bids, so complete without a final + // result. + OnLoadInterestGroupsComplete(/*auction_result=*/AuctionResult::kSuccess); +} + +void AuctionRunner::Auction::OnLoadInterestGroupsComplete( + AuctionResult auction_result) { + DCHECK(load_interest_groups_callback_); + DCHECK(!final_auction_result_); + + // `final_auction_result_` should only be set to kSuccess when the entire + // auction is complete. + bool success = auction_result == AuctionResult::kSuccess; + if (!success) + final_auction_result_ = auction_result; + std::move(load_interest_groups_callback_).Run(success); +} + std::unique_ptr<AuctionRunner> AuctionRunner::CreateAndStart( AuctionWorkletManager* auction_worklet_manager, InterestGroupManagerImpl* interest_group_manager, @@ -120,8 +229,12 @@ RunAuctionCallback callback) : auction_worklet_manager_(auction_worklet_manager), interest_group_manager_(interest_group_manager), - auction_config_(std::move(auction_config)), - callback_(std::move(callback)) {} + owned_auction_config_(std::move(auction_config)), + callback_(std::move(callback)), + auction_(owned_auction_config_.get(), + auction_worklet_manager, + interest_group_manager, + /*auction_start_time=*/base::Time::Now()) {} AuctionRunner::~AuctionRunner() = default; @@ -196,7 +309,7 @@ const std::vector<std::string>& errors) { DCHECK(callback_); - errors_.insert(errors_.end(), errors.begin(), errors.end()); + auction_.errors_.insert(auction_.errors_.end(), errors.begin(), errors.end()); RecordResult(result); ClosePipes(); @@ -212,110 +325,60 @@ this, /*render_url=*/absl::nullopt, /*ad_component_urls=*/absl::nullopt, /*report_urls=*/{}, std::move(debug_loss_report_urls_), - std::move(debug_win_report_urls_), std::move(errors_)); + std::move(debug_win_report_urls_), std::move(auction_.errors_)); } void AuctionRunner::StartAuction( IsInterestGroupApiAllowedCallback is_interest_group_api_allowed_callback) { - if (!is_interest_group_api_allowed_callback.Run( - ContentBrowserClient::InterestGroupApiOperation::kSell, - auction_config_->seller)) { - FailAuctionAsync(AuctionResult::kSellerRejected); - return; - } - - const auto& buyers = auction_config_->auction_ad_config_non_shared_params - ->interest_group_buyers; - if (buyers) { - for (const auto& buyer : *buyers) { - if (!is_interest_group_api_allowed_callback.Run( - ContentBrowserClient::InterestGroupApiOperation::kBuy, buyer)) { - continue; - } - interest_group_manager_->GetInterestGroupsForOwner( - buyer, base::BindOnce(&AuctionRunner::OnInterestGroupRead, - weak_ptr_factory_.GetWeakPtr())); - ++num_pending_buyers_; - } - } - - if (num_pending_buyers_ == 0) - FailAuctionAsync(AuctionResult::kNoInterestGroups); + auction_.LoadInterestGroups( + is_interest_group_api_allowed_callback, + base::BindOnce(&AuctionRunner::OnInterestGroupsLoaded, + base::Unretained(this))); } -void AuctionRunner::OnInterestGroupRead( - std::vector<StorageInterestGroup> interest_groups) { - DCHECK_GT(num_pending_buyers_, 0u); - --num_pending_buyers_; - - if (!interest_groups.empty()) { - for (auto bidder = std::make_move_iterator(interest_groups.begin()); - bidder != std::make_move_iterator(interest_groups.end()); ++bidder) { - // Ignore interest groups with no bidding script or no ads. - if (!bidder->interest_group.bidding_url) - continue; - if (bidder->interest_group.ads->empty()) - continue; - bid_states_.emplace_back(BidState()); - bid_states_.back().bidder = std::move(*bidder); - } - ++num_owners_with_interest_groups_; - } - - // Wait for more buyers to be loaded, if there are still some pending. - if (num_pending_buyers_ > 0) - return; - - // Record histograms about the interest groups participating in the auction. - UMA_HISTOGRAM_COUNTS_1000("Ads.InterestGroup.Auction.NumInterestGroups", - bid_states_.size()); - UMA_HISTOGRAM_COUNTS_100( - "Ads.InterestGroup.Auction.NumOwnersWithInterestGroups", - num_owners_with_interest_groups_); - - // If no interest groups were found, end the auction without a winner. - if (bid_states_.empty()) { - FailAuction(AuctionResult::kNoInterestGroups); +void AuctionRunner::OnInterestGroupsLoaded(bool success) { + if (!success) { + FailAuction(*auction_.final_auction_result_); return; } - num_bids_not_sent_to_seller_worklet_ = bid_states_.size(); - outstanding_bids_ = num_bids_not_sent_to_seller_worklet_; + auction_.num_bids_not_sent_to_seller_worklet_ = auction_.bid_states_.size(); + auction_.outstanding_bids_ = auction_.num_bids_not_sent_to_seller_worklet_; RequestSellerWorklet(); RequestBidderWorklets(); } void AuctionRunner::RequestSellerWorklet() { if (auction_worklet_manager_->RequestSellerWorklet( - auction_config_->decision_logic_url, - auction_config_->trusted_scoring_signals_url, + auction_.config_->decision_logic_url, + auction_.config_->trusted_scoring_signals_url, base::BindOnce(&AuctionRunner::OnSellerWorkletReceived, base::Unretained(this)), base::BindOnce(&AuctionRunner::OnSellerWorkletFatalError, base::Unretained(this)), - seller_worklet_handle_)) { + auction_.seller_worklet_handle_)) { OnSellerWorkletReceived(); } } void AuctionRunner::OnSellerWorkletReceived() { - DCHECK(!seller_worklet_received_); + DCHECK(!auction_.seller_worklet_received_); - seller_worklet_received_ = true; - for (auto& unscored_bid : unscored_bids_) { + auction_.seller_worklet_received_ = true; + for (auto& unscored_bid : auction_.unscored_bids_) { ScoreBid(std::move(unscored_bid)); } - unscored_bids_.clear(); + auction_.unscored_bids_.clear(); } void AuctionRunner::RequestBidderWorklets() { // Auctions are only run when there are bidders participating. As-is, an // empty bidder vector here would result in synchronously calling back into // the creator, which isn't allowed. - DCHECK(!bid_states_.empty()); + DCHECK(!auction_.bid_states_.empty()); // Request processes for all bidder worklets. - for (auto& bid_state : bid_states_) { + for (auto& bid_state : auction_.bid_states_) { if (RequestBidderWorklet( bid_state, base::BindOnce(&AuctionRunner::OnBidderWorkletReceived, @@ -349,9 +412,10 @@ interest_group.name, interest_group.trusted_bidding_signals_keys, interest_group.user_bidding_signals, interest_group.ads, interest_group.ad_components), - auction_config_->auction_ad_config_non_shared_params->auction_signals, - PerBuyerSignals(bid_state), auction_config_->seller, - bid_state->bidder.bidding_browser_signals.Clone(), auction_start_time_, + auction_.config_->auction_ad_config_non_shared_params->auction_signals, + PerBuyerSignals(bid_state), auction_.config_->seller, + bid_state->bidder.bidding_browser_signals.Clone(), + auction_.auction_start_time_, base::BindOnce(&AuctionRunner::OnGenerateBidComplete, weak_ptr_factory_.GetWeakPtr(), bid_state)); @@ -408,10 +472,10 @@ const absl::optional<GURL>& debug_win_report_url, const std::vector<std::string>& errors) { DCHECK(!state->made_bid); - DCHECK_GT(num_bids_not_sent_to_seller_worklet_, 0); - DCHECK_GT(outstanding_bids_, 0); + DCHECK_GT(auction_.num_bids_not_sent_to_seller_worklet_, 0); + DCHECK_GT(auction_.outstanding_bids_, 0); - errors_.insert(errors_.end(), errors.begin(), errors.end()); + auction_.errors_.insert(auction_.errors_.end(), errors.begin(), errors.end()); // Release the worklet. If it wins the auction, it will be requested again to // invoke its ReportWin() method. @@ -433,21 +497,23 @@ } if (!bid) { - --num_bids_not_sent_to_seller_worklet_; + --auction_.num_bids_not_sent_to_seller_worklet_; // If this is the only bid that yet to be sent to the seller worklet, and // the seller worklet has loaded, then tell the seller worklet to send any // pending scoring signals request to complete the auction more quickly. - if (num_bids_not_sent_to_seller_worklet_ == 0) - seller_worklet_handle_->GetSellerWorklet()->SendPendingSignalsRequests(); - --outstanding_bids_; + if (auction_.num_bids_not_sent_to_seller_worklet_ == 0) { + auction_.seller_worklet_handle_->GetSellerWorklet() + ->SendPendingSignalsRequests(); + } + --auction_.outstanding_bids_; MaybeCompleteAuction(); return; } state->bidder_debug_win_report_url = std::move(debug_win_report_url); state->made_bid = true; - if (!seller_worklet_received_) { - unscored_bids_.emplace_back(std::move(bid)); + if (!auction_.seller_worklet_received_) { + auction_.unscored_bids_.emplace_back(std::move(bid)); } else { ScoreBid(std::move(bid)); } @@ -455,15 +521,15 @@ void AuctionRunner::ScoreBid(std::unique_ptr<Bid> bid) { DCHECK(bid); - DCHECK_GT(num_bids_not_sent_to_seller_worklet_, 0); - DCHECK_GT(outstanding_bids_, 0); + DCHECK_GT(auction_.num_bids_not_sent_to_seller_worklet_, 0); + DCHECK_GT(auction_.outstanding_bids_, 0); DCHECK(bid->bid_state->made_bid); - DCHECK(seller_worklet_received_); + DCHECK(auction_.seller_worklet_received_); Bid* bid_raw = bid.get(); - seller_worklet_handle_->GetSellerWorklet()->ScoreAd( + auction_.seller_worklet_handle_->GetSellerWorklet()->ScoreAd( bid_raw->ad_metadata, bid_raw->bid, - auction_config_->auction_ad_config_non_shared_params.Clone(), + auction_.config_->auction_ad_config_non_shared_params.Clone(), bid_raw->interest_group->owner, bid_raw->render_url, bid_raw->ad_components ? *bid_raw->ad_components : std::vector<GURL>(), bid_raw->bid_duration.InMilliseconds(), @@ -473,9 +539,10 @@ // If this was the last bid that needed to be passed to ScoreAd(), tell the // SellerWorklet no more bids are coming, so it can send a request for any // needed scoring signals now, if needed. - --num_bids_not_sent_to_seller_worklet_; - if (num_bids_not_sent_to_seller_worklet_ == 0) { - seller_worklet_handle_->GetSellerWorklet()->SendPendingSignalsRequests(); + --auction_.num_bids_not_sent_to_seller_worklet_; + if (auction_.num_bids_not_sent_to_seller_worklet_ == 0) { + auction_.seller_worklet_handle_->GetSellerWorklet() + ->SendPendingSignalsRequests(); } } @@ -487,7 +554,7 @@ const absl::optional<GURL>& debug_loss_report_url, const absl::optional<GURL>& debug_win_report_url, const std::vector<std::string>& errors) { - --outstanding_bids_; + --auction_.outstanding_bids_; // If `debug_loss_report_url` or `debug_win_report_url` is not a valid HTTPS // URL, the auction should fail because the worklet is compromised. @@ -503,7 +570,7 @@ FailAuction(AuctionResult::kBadMojoMessage); return; } - errors_.insert(errors_.end(), errors.begin(), errors.end()); + auction_.errors_.insert(auction_.errors_.end(), errors.begin(), errors.end()); bid->bid_state->seller_debug_loss_report_url = std::move(debug_loss_report_url); @@ -513,23 +580,23 @@ // A score <= 0 means the seller rejected the bid. if (score > 0) { - if (!top_bid_ || score > top_bid_->score) { + if (!auction_.top_bid_ || score > auction_.top_bid_->score) { // If there's no previous top bidder, or the bidder has the highest score, // need to replace the previous top bidder. - num_top_bids_ = 1; + auction_.num_top_bids_ = 1; is_top_bid = true; - } else if (score == top_bid_->score) { + } else if (score == auction_.top_bid_->score) { // If there's a tie, replace the top-bidder with 1-in-`num_top_bidders_` // chance. This is the select random value from a stream with fixed // storage problem. - ++num_top_bids_; - if (1 == base::RandInt(1, num_top_bids_)) + ++auction_.num_top_bids_; + if (1 == base::RandInt(1, auction_.num_top_bids_)) is_top_bid = true; } } if (is_top_bid) { - top_bid_ = std::make_unique<ScoredBid>( + auction_.top_bid_ = std::make_unique<ScoredBid>( score, has_data_version ? data_version : absl::optional<uint32_t>(), std::move(bid)); } @@ -540,7 +607,7 @@ absl::optional<std::string> AuctionRunner::PerBuyerSignals( const BidState* state) { const auto& per_buyer_signals = - auction_config_->auction_ad_config_non_shared_params->per_buyer_signals; + auction_.config_->auction_ad_config_non_shared_params->per_buyer_signals; if (per_buyer_signals.has_value()) { auto it = per_buyer_signals.value().find(state->bidder.interest_group.owner); @@ -556,14 +623,14 @@ // Since all bids have been scored, they also should have all been sent to the // SellerWorklet by this point. - DCHECK_EQ(0, num_bids_not_sent_to_seller_worklet_); + DCHECK_EQ(0, auction_.num_bids_not_sent_to_seller_worklet_); // Record which interest groups bid. // // TODO(mmenke): Maybe this should be recorded at bid time, and the interest // group thrown away if it's not the top bid? bool some_bidder_bid = false; - for (BidState& bid_state : bid_states_) { + for (BidState& bid_state : auction_.bid_states_) { if (bid_state.made_bid) { some_bidder_bid = true; interest_group_manager_->RecordInterestGroupBid( @@ -573,8 +640,8 @@ } BidState* top_bidder = nullptr; - if (top_bid_) { - top_bidder = top_bid_->bid->bid_state; + if (auction_.top_bid_) { + top_bidder = auction_.top_bid_->bid->bid_state; if (top_bidder && top_bidder->bidder_debug_win_report_url.has_value()) { debug_win_report_urls_.push_back( top_bidder->bidder_debug_win_report_url.value()); @@ -585,7 +652,7 @@ } } - for (BidState& bid_state : bid_states_) { + for (BidState& bid_state : auction_.bid_states_) { if (&bid_state == top_bidder) continue; if (bid_state.bidder_debug_loss_report_url.has_value()) { @@ -598,7 +665,7 @@ } } - if (!top_bid_) { + if (!auction_.top_bid_) { FailAuction(some_bidder_bid ? AuctionResult::kAllBidsRejected : AuctionResult::kNoBids); return; @@ -609,13 +676,14 @@ } void AuctionRunner::ReportSellerResult() { - DCHECK(top_bid_); + DCHECK(auction_.top_bid_); - seller_worklet_handle_->GetSellerWorklet()->ReportResult( - auction_config_->auction_ad_config_non_shared_params.Clone(), - top_bid_->bid->interest_group->owner, top_bid_->bid->render_url, - top_bid_->bid->bid, top_bid_->score, top_bid_->data_version.value_or(0), - top_bid_->data_version.has_value(), + auction_.seller_worklet_handle_->GetSellerWorklet()->ReportResult( + auction_.config_->auction_ad_config_non_shared_params.Clone(), + auction_.top_bid_->bid->interest_group->owner, + auction_.top_bid_->bid->render_url, auction_.top_bid_->bid->bid, + auction_.top_bid_->score, auction_.top_bid_->data_version.value_or(0), + auction_.top_bid_->data_version.has_value(), base::BindOnce(&AuctionRunner::OnReportSellerResultComplete, weak_ptr_factory_.GetWeakPtr())); } @@ -625,7 +693,7 @@ const absl::optional<GURL>& seller_report_url, const std::vector<std::string>& errors) { // There should be no other report URLs at this point. - DCHECK(report_urls_.empty()); + DCHECK(auction_.report_urls_.empty()); if (seller_report_url) { if (!IsUrlValid(*seller_report_url)) { @@ -634,22 +702,22 @@ return; } - report_urls_.push_back(*seller_report_url); + auction_.report_urls_.push_back(*seller_report_url); } - errors_.insert(errors_.end(), errors.begin(), errors.end()); + auction_.errors_.insert(auction_.errors_.end(), errors.begin(), errors.end()); LoadBidderWorkletToReportBidWin(signals_for_winner); } void AuctionRunner::LoadBidderWorkletToReportBidWin( const absl::optional<std::string>& signals_for_winner) { - DCHECK(top_bid_); + DCHECK(auction_.top_bid_); // Worklet handle should have been destroyed once the bid was generated. - DCHECK(!top_bid_->bid->bid_state->worklet_handle); + DCHECK(!auction_.top_bid_->bid->bid_state->worklet_handle); if (RequestBidderWorklet( - *top_bid_->bid->bid_state, + *auction_.top_bid_->bid->bid_state, base::BindOnce(&AuctionRunner::ReportBidWin, base::Unretained(this), signals_for_winner), base::BindOnce(&AuctionRunner::OnWinningBidderWorkletFatalError, @@ -660,7 +728,7 @@ void AuctionRunner::ReportBidWin( const absl::optional<std::string>& signals_for_winner) { - DCHECK(top_bid_); + DCHECK(auction_.top_bid_); std::string signals_for_winner_arg; if (signals_for_winner) { @@ -674,20 +742,22 @@ signals_for_winner_arg = "null"; } - top_bid_->bid->bid_state->worklet_handle->GetBidderWorklet()->ReportWin( - top_bid_->bid->interest_group->name, - auction_config_->auction_ad_config_non_shared_params->auction_signals, - PerBuyerSignals(top_bid_->bid->bid_state), signals_for_winner_arg, - top_bid_->bid->render_url, top_bid_->bid->bid, auction_config_->seller, - base::BindOnce(&AuctionRunner::OnReportBidWinComplete, - weak_ptr_factory_.GetWeakPtr())); + auction_.top_bid_->bid->bid_state->worklet_handle->GetBidderWorklet() + ->ReportWin(auction_.top_bid_->bid->interest_group->name, + auction_.config_->auction_ad_config_non_shared_params + ->auction_signals, + PerBuyerSignals(auction_.top_bid_->bid->bid_state), + signals_for_winner_arg, auction_.top_bid_->bid->render_url, + auction_.top_bid_->bid->bid, auction_.config_->seller, + base::BindOnce(&AuctionRunner::OnReportBidWinComplete, + weak_ptr_factory_.GetWeakPtr())); } void AuctionRunner::OnReportBidWinComplete( const absl::optional<GURL>& bidder_report_url, const std::vector<std::string>& errors) { // There should be at most one other report URL at this point. - DCHECK_LE(report_urls_.size(), 1u); + DCHECK_LE(auction_.report_urls_.size(), 1u); if (bidder_report_url) { if (!IsUrlValid(*bidder_report_url)) { @@ -696,10 +766,10 @@ return; } - report_urls_.push_back(*bidder_report_url); + auction_.report_urls_.push_back(*bidder_report_url); } - errors_.insert(errors_.end(), errors.begin(), errors.end()); + auction_.errors_.insert(auction_.errors_.end(), errors.begin(), errors.end()); ReportSuccess(); } @@ -713,52 +783,49 @@ AuctionResult::kWinningBidderWorkletCrashed, // Ignore default error message in case of crash. Instead, use a more // specific one. - {base::StrCat({top_bid_->bid->interest_group->bidding_url->spec(), - " crashed while trying to run reportWin()."})}); + {base::StrCat( + {auction_.top_bid_->bid->interest_group->bidding_url->spec(), + " crashed while trying to run reportWin()."})}); } else { // An error while reloading the worklet to call ReportWin() does not // currently fail the auction. - errors_.insert(errors_.end(), errors.begin(), errors.end()); + auction_.errors_.insert(auction_.errors_.end(), errors.begin(), + errors.end()); ReportSuccess(); } } -void AuctionRunner::FailAuctionAsync(AuctionResult result) { - base::SequencedTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(&AuctionRunner::FailAuction, - weak_ptr_factory_.GetWeakPtr(), result, - std::vector<std::string>{})); -} - void AuctionRunner::ReportSuccess() { DCHECK(callback_); - DCHECK(top_bid_); - DCHECK_LE(report_urls_.size(), 2u); + DCHECK(auction_.top_bid_); + DCHECK_LE(auction_.report_urls_.size(), 2u); ClosePipes(); RecordResult(AuctionResult::kSuccess); std::string ad_metadata; - if (top_bid_->bid->bid_ad->metadata) { + if (auction_.top_bid_->bid->bid_ad->metadata) { //`metadata` is already in JSON so no quotes are needed. - ad_metadata = - base::StringPrintf(R"({"render_url":"%s","metadata":%s})", - top_bid_->bid->render_url.spec().c_str(), - top_bid_->bid->bid_ad->metadata.value().c_str()); + ad_metadata = base::StringPrintf( + R"({"render_url":"%s","metadata":%s})", + auction_.top_bid_->bid->render_url.spec().c_str(), + auction_.top_bid_->bid->bid_ad->metadata.value().c_str()); } else { - ad_metadata = base::StringPrintf(R"({"render_url":"%s"})", - top_bid_->bid->render_url.spec().c_str()); + ad_metadata = + base::StringPrintf(R"({"render_url":"%s"})", + auction_.top_bid_->bid->render_url.spec().c_str()); } interest_group_manager_->RecordInterestGroupWin( - top_bid_->bid->interest_group->owner, top_bid_->bid->interest_group->name, - ad_metadata); + auction_.top_bid_->bid->interest_group->owner, + auction_.top_bid_->bid->interest_group->name, ad_metadata); std::move(callback_).Run( - this, top_bid_->bid->render_url, top_bid_->bid->ad_components, - std::move(report_urls_), std::move(debug_loss_report_urls_), - std::move(debug_win_report_urls_), std::move(errors_)); + this, auction_.top_bid_->bid->render_url, + auction_.top_bid_->bid->ad_components, std::move(auction_.report_urls_), + std::move(debug_loss_report_urls_), std::move(debug_win_report_urls_), + std::move(auction_.errors_)); } void AuctionRunner::ClosePipes() { @@ -766,10 +833,10 @@ // worklet creation callbacks. weak_ptr_factory_.InvalidateWeakPtrs(); - for (BidState& bid_state : bid_states_) { + for (BidState& bid_state : auction_.bid_states_) { bid_state.worklet_handle.reset(); } - seller_worklet_handle_.reset(); + auction_.seller_worklet_handle_.reset(); } void AuctionRunner::RecordResult(AuctionResult result) const { @@ -778,19 +845,20 @@ // Only record time of full auctions and aborts. switch (result) { case AuctionResult::kAborted: - UMA_HISTOGRAM_MEDIUM_TIMES("Ads.InterestGroup.Auction.AbortTime", - base::Time::Now() - auction_start_time_); + UMA_HISTOGRAM_MEDIUM_TIMES( + "Ads.InterestGroup.Auction.AbortTime", + base::Time::Now() - auction_.auction_start_time_); break; case AuctionResult::kNoBids: case AuctionResult::kAllBidsRejected: UMA_HISTOGRAM_MEDIUM_TIMES( "Ads.InterestGroup.Auction.CompletedWithoutWinnerTime", - base::Time::Now() - auction_start_time_); + base::Time::Now() - auction_.auction_start_time_); break; case AuctionResult::kSuccess: UMA_HISTOGRAM_MEDIUM_TIMES( "Ads.InterestGroup.Auction.AuctionWithWinnerTime", - base::Time::Now() - auction_start_time_); + base::Time::Now() - auction_.auction_start_time_); break; default: break;
diff --git a/content/browser/interest_group/auction_runner.h b/content/browser/interest_group/auction_runner.h index f3fd30bc..5b3b353c 100644 --- a/content/browser/interest_group/auction_runner.h +++ b/content/browser/interest_group/auction_runner.h
@@ -121,7 +121,7 @@ // // `result` is used for logging purposes only. // - // `errors` is appended to `errors_`. + //`errors` is appended to `errors_`. // // Public so that the owner can fail the auction on teardown, to invoke any // pending Mojo callbacks. @@ -232,6 +232,143 @@ const std::unique_ptr<Bid> bid; }; + // Handles running an auction rooted at a given AuctionConfig. Separate from + // AuctionRunner so that component auctions can use the same logic as the + // top-level auction. + // + // When complete, Auctions will have three phases, with phase transitions + // handled by the parent class. All phases complete asynchronously: + // + // * Loading interest groups phase: This loads interest groups that can + // participate in an auction. Waiting for all component auctions to complete + // this phase before advance to the next ensures that if any auctions share + // bidder worklets, they'll all be loaded together, and only send out a single + // trusted bidding signals request. + // + // * Bidding/scoring phase: This phase loads bidder and seller worklets, + // generates bids, scores bids, and the highest scoring bid for each component + // auction is passed to its parent auction, which also scores it. When this + // phase completes, the winner will have been decided. + // + // * ReportResult / ReportWin phase: This phase invokes ReportResult() on + // winning seller worklets and ReportWin() in the winning bidder worklet. + class Auction { + public: + // Callback that's invoked once interest groups have been loaded. Always + // invoked asynchronously. + using LoadInterestGroupsCallback = base::OnceCallback<void(bool success)>; + + // All passed in raw pointers must remain valid until the Auction is + // destroyed. `config` is typically owned by the AuctionRunner's + // `owned_auction_config_` field. + Auction(blink::mojom::AuctionAdConfig* config, + AuctionWorkletManager* auction_worklet_manager, + InterestGroupManagerImpl* interest_group_manager, + base::Time auction_start_time); + + ~Auction(); + + // Starts loading the interest groups that can participate in an auction. + // + // Both seller and buyer origins are filtered by + // `is_interest_group_api_allowed`, and any any not allowed to use the API + // are excluded from participating in the auction. + // + // Invokes `load_interest_groups_callback` asynchronously on completion. + // Passes it false if there are no interest groups that may participate in + // the auction (possibly because sellers aren't allowed to participate in + // the auction) + void LoadInterestGroups( + IsInterestGroupApiAllowedCallback + is_interest_group_api_allowed_callback, + LoadInterestGroupsCallback load_interest_groups_callback); + + private: + // TODO(mmenke): Remove this once Auction fully manages its own state. + friend class AuctionRunner; + + // Adds `interest_groups` to `bid_states_`. If all bidders have been loaded, + // calls OnLoadInterestGroupsComplete(). + void OnInterestGroupRead(std::vector<StorageInterestGroup> interest_groups); + + // Invoked once the interest group load phase has completed. Never called + // synchronously from LoadInterestGroups(), to avoid reentrancy. + // `auction_result` is the result of trying to load the interest groups that + // can participate in the auction. It's AuctionResult::kSuccess if there are + // interest groups that can take part in the auction, and a failure value + // otherwise. + void OnLoadInterestGroupsComplete(AuctionResult auction_result); + + const raw_ptr<AuctionWorkletManager> auction_worklet_manager_; + const raw_ptr<InterestGroupManagerImpl> interest_group_manager_; + + // Configuration of this auction. + raw_ptr<const blink::mojom::AuctionAdConfig> config_; + + // Final result of the auction, once completed. Null before completion. + absl::optional<AuctionResult> final_auction_result_; + + // The number of buyers with pending interest group loads from storage. + // Decremented each time OnInterestGroupRead() is invoked. + // `load_interest_groups_callback` is invoked once this hits 0. + size_t num_pending_buyers_ = 0; + LoadInterestGroupsCallback load_interest_groups_callback_; + + // True once a seller worklet has been received from the + // AuctionWorkletManager. + bool seller_worklet_received_ = false; + + // Number of bids that have yet to be sent to the SellerWorklet. This + // includes BidderWorklets that have not yet been loaded, those whose + // GenerateBid() method is currently being run, and those that are waiting + // on the seller worklet to load. Decremented when GenerateBid() fails to + // generate a bid, or just after invoking the SellerWorklet's ScoreAd() + // method. When this reaches 0, the SellerWorklet's + // SendPendingSignalsRequests() should be invoked, so it can send any + // pending scoring signals requests. + int num_bids_not_sent_to_seller_worklet_; + // Number of bids which the seller has not yet finished scoring. These bids + // may be fetching URLs, generating bids, waiting for the seller worklet to + // load, or the seller worklet may be scoring their bids. When this reaches + // 0, the bid with the highest score is the winner, and the auction is + // completed, apart from reporting the result. + int outstanding_bids_; + + // State of all loaded interest groups. + std::vector<BidState> bid_states_; + + // Bids waiting on the seller worklet to load before scoring. Does not + // include bids that are currently waiting on the worklet's ScoreAd() method + // to complete. + std::vector<std::unique_ptr<Bid>> unscored_bids_; + + // The time the auction started. Use a single base time for all Worklets, to + // present a more consistent view of the universe. + const base::Time auction_start_time_; + + // The number of owners with InterestGroups participating in an auction. + int num_owners_with_interest_groups_ = 0; + + // The highest scoring bid so far. Null if no bid has been accepted yet. + std::unique_ptr<ScoredBid> top_bid_; + // Number of bidders with the same score as `top_bidder`. + size_t num_top_bids_ = 0; + + // Holds a reference to the SellerWorklet used by the auction. + std::unique_ptr<AuctionWorkletManager::WorkletHandle> + seller_worklet_handle_; + + // Report URLs from reportResult() and reportWin() methods. Returned to + // caller for it to deal with, so the Auction itself can be deleted at the + // end of the auction. + std::vector<GURL> report_urls_; + + // All errors reported by worklets thus far. + std::vector<std::string> errors_; + + base::WeakPtrFactory<Auction> weak_ptr_factory_{this}; + }; + AuctionRunner(AuctionWorkletManager* auction_worklet_manager, InterestGroupManagerImpl* interest_group_manager, blink::mojom::AuctionAdConfigPtr auction_config, @@ -247,22 +384,14 @@ const absl::optional<GURL>& debug_loss_report_url, const absl::optional<GURL>& debug_win_report_url); - // Checks that the seller is allowed to partipate in an auction, and starts - // retrieving all interest groups owned buyer origins listed in - // `auction_config_` from storage, except those for which - // `is_interest_group_api_allowed_callback` returns false. - // - // OnInterestGroupRead() will be invoked with the lookup results for each - // buyer origin. If the seller may not participate in an auction, or no listed - // interest groups buyers may use the interest group API, asynchronously fails - // the auction. + // Tells `auction_` to start loading interest groups. void StartAuction( IsInterestGroupApiAllowedCallback is_interest_group_api_allowed_callback); - // Adds `interest_groups` to `bid_states_`. Continues retrieving bidders from - // `pending_buyers_` if any have not been retrieved yet. Otherwise, invokes - // StartBidding(). - void OnInterestGroupRead(std::vector<StorageInterestGroup> interest_groups); + // Invoked asynchronously by `auction_` once all interest groups have loaded. + // Fails the auction if `success` is false. Otherwise, starts loading + // worklets. + void OnInterestGroupsLoaded(bool success); // Requests a seller worklet from the AuctionWorkletManager. void RequestSellerWorklet(); @@ -313,7 +442,7 @@ const std::vector<std::string>& errors); // True if all bid results and the seller script load are complete. - bool AllBidsScored() const { return outstanding_bids_ == 0; } + bool AllBidsScored() const { return auction_.outstanding_bids_ == 0; } // Calls into the seller asynchronously to score the passed in bid. void ScoreBid(std::unique_ptr<Bid> bid); @@ -355,9 +484,6 @@ AuctionWorkletManager::FatalErrorType fatal_error_type, const std::vector<std::string>& errors); - // Invokes FailAuction asynchronously. - void FailAuctionAsync(AuctionResult result); - // Completes the auction, invoking `callback_` and preventing any future // calls into `this` by closing mojo pipes and disposing of weak pointers. The // owner must be able to safely delete `this` when the callback is invoked. @@ -382,69 +508,16 @@ const raw_ptr<InterestGroupManagerImpl> interest_group_manager_; // Configuration. - blink::mojom::AuctionAdConfigPtr auction_config_; - // The number of buyers with pending interest group loads from storage. - // Decremented each time OnInterestGroupRead() is invoked. The auction is - // started once this hits 0. - size_t num_pending_buyers_ = 0; + blink::mojom::AuctionAdConfigPtr owned_auction_config_; RunAuctionCallback callback_; - // True once a seller worklet has been received from the - // AuctionWorkletManager. - bool seller_worklet_received_ = false; - - // Number of bids that have yet to be sent to the SellerWorklet. This - // includes BidderWorklets that have not yet been loaded, those whose - // GenerateBid() method is currently being run, and those that are waiting on - // the seller worklet to load. Decremented when GenerateBid() fails to - // generate a bid, or just after invoking the SellerWorklet's ScoreAd() - // method. When this reaches 0, the SellerWorklet's - // SendPendingSignalsRequests() should be invoked, so it can send any pending - // scoring signals requests. - int num_bids_not_sent_to_seller_worklet_; - // Number of bids which the seller has not yet finished scoring. These bids - // may be fetching URLs, generating bids, waiting for the seller worklet to - // load, or the seller worklet may be scoring their bids. When this reaches 0, - // the bid with the highest score is the winner, and the auction is completed, - // apart from reporting the result. - int outstanding_bids_; - - // State of all loaded interest groups. - std::vector<BidState> bid_states_; - - // Bids waiting on the seller worklet to load before scoring. Does not include - // bids that are currently waiting on the worklet's ScoreAd() method to - // complete. - std::vector<std::unique_ptr<Bid>> unscored_bids_; - - // The time the auction started. Use a single base time for all Worklets, to - // present a more consistent view of the universe. - const base::Time auction_start_time_ = base::Time::Now(); - - // The number of owners with InterestGroups participating in an auction. - int num_owners_with_interest_groups_ = 0; - - // The highest scoring bid so far. Null if no bid has been accepted yet. - std::unique_ptr<ScoredBid> top_bid_; - // Number of bidders with the same score as `top_bid_`. - size_t num_top_bids_ = 0; - - // Holds a reference to the SellerWorklet used by the auction. - std::unique_ptr<AuctionWorkletManager::WorkletHandle> seller_worklet_handle_; - - // Report URLs from reportResult() and reportWin() methods. Returned to caller - // for it to deal with, so the AuctionRunner itself can be deleted at the end - // of the auction. - std::vector<GURL> report_urls_; + Auction auction_; // URLs of forDebuggingOnly.reportAdAuctionLoss(url) and // forDebuggingOnly.reportAdAuctionWin(url). std::vector<GURL> debug_loss_report_urls_; std::vector<GURL> debug_win_report_urls_; - // All errors reported by worklets thus far. - std::vector<std::string> errors_; - base::WeakPtrFactory<AuctionRunner> weak_ptr_factory_{this}; };
diff --git a/content/browser/media/key_system_support_impl_unittest.cc b/content/browser/media/key_system_support_impl_unittest.cc index dc71090b..ac2a37b6 100644 --- a/content/browser/media/key_system_support_impl_unittest.cc +++ b/content/browser/media/key_system_support_impl_unittest.cc
@@ -133,14 +133,25 @@ base::Version(kVersion), base::FilePath::FromUTF8Unsafe(kTestPath))); } + void OnIsKeySystemSupported(base::OnceClosure done_cb, + bool is_supported, + media::mojom::KeySystemCapabilityPtr capability) { + is_supported_ = is_supported; + capability_ = std::move(capability); + std::move(done_cb).Run(); + } + // Determines if |key_system| is registered. If it is, updates |codecs_| // and |persistent_|. bool IsSupported(const std::string& key_system) { DVLOG(1) << __func__; - bool is_supported = false; - key_system_support_->IsKeySystemSupported(key_system, &is_supported, - &capability_); - return is_supported; + base::RunLoop run_loop; + key_system_support_->IsKeySystemSupported( + key_system, + base::BindOnce(&KeySystemSupportImplTest::OnIsKeySystemSupported, + base::Unretained(this), run_loop.QuitClosure())); + run_loop.Run(); + return is_supported_; } [[maybe_unused]] gpu::GpuFeatureInfo GetGpuFeatureInfoWithOneDisabled( @@ -180,6 +191,7 @@ BrowserTaskEnvironment task_environment_; // Updated by IsSupported(). + bool is_supported_ = false; media::mojom::KeySystemCapabilityPtr capability_; };
diff --git a/content/browser/net/network_errors_listing_ui.cc b/content/browser/net/network_errors_listing_ui.cc index f04de9b8..1f0f6cb4 100644 --- a/content/browser/net/network_errors_listing_ui.cc +++ b/content/browser/net/network_errors_listing_ui.cc
@@ -78,8 +78,9 @@ NetworkErrorsListingUI::NetworkErrorsListingUI(WebUI* web_ui) : WebUIController(web_ui) { // Set up the chrome://network-errors source. - WebUIDataSource* html_source = - WebUIDataSource::Create(kChromeUINetworkErrorsListingHost); + WebUIDataSource* html_source = WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), + kChromeUINetworkErrorsListingHost); // Add required resources. html_source->UseStringsJs(); @@ -92,10 +93,6 @@ base::BindRepeating(&ShouldHandleWebUIRequestCallback), base::BindRepeating(&HandleWebUIRequestCallback, web_ui->GetWebContents()->GetBrowserContext())); - - BrowserContext* browser_context = - web_ui->GetWebContents()->GetBrowserContext(); - WebUIDataSource::Add(browser_context, html_source); } } // namespace content
diff --git a/content/browser/prerender/prerender_internals_ui.cc b/content/browser/prerender/prerender_internals_ui.cc index 2985629..68e4590a 100644 --- a/content/browser/prerender/prerender_internals_ui.cc +++ b/content/browser/prerender/prerender_internals_ui.cc
@@ -19,18 +19,15 @@ PrerenderInternalsUI::PrerenderInternalsUI(WebUI* web_ui) : WebUIController(web_ui) { // Set up the chrome://prerender-internals source. - WebUIDataSource* source = - WebUIDataSource::Create(kChromeUIPrerenderInternalsHost); + WebUIDataSource* source = WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), + kChromeUIPrerenderInternalsHost); // Add required resources. source->AddResourcePath("prerender_internals.js", IDR_PRERENDER_INTERNALS_JS); source->AddResourcePath("prerender_internals.mojom-webui.js", IDR_PRERENDER_INTERNALS_MOJO_JS); source->SetDefaultResource(IDR_PRERENDER_INTERNALS_HTML); - - BrowserContext* browser_context = - web_ui->GetWebContents()->GetBrowserContext(); - WebUIDataSource::Add(browser_context, source); } WEB_UI_CONTROLLER_TYPE_IMPL(PrerenderInternalsUI)
diff --git a/content/browser/process_internals/process_internals_ui.cc b/content/browser/process_internals/process_internals_ui.cc index 3354b1b5..99e5e8e 100644 --- a/content/browser/process_internals/process_internals_ui.cc +++ b/content/browser/process_internals/process_internals_ui.cc
@@ -31,8 +31,9 @@ web_ui->SetBindings(BINDINGS_POLICY_NONE); // Create a WebUIDataSource to serve the HTML/JS files to the WebUI. - WebUIDataSource* source = - WebUIDataSource::Create(kChromeUIProcessInternalsHost); + WebUIDataSource* source = WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), + kChromeUIProcessInternalsHost); source->AddResourcePath("process_internals.js", IDR_PROCESS_INTERNALS_JS); source->AddResourcePath("process_internals.css", IDR_PROCESS_INTERNALS_CSS); @@ -42,8 +43,6 @@ source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::TrustedTypes, "trusted-types static-types;"); - - WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), source); } WEB_UI_CONTROLLER_TYPE_IMPL(ProcessInternalsUI)
diff --git a/content/browser/quota/quota_internals_ui.cc b/content/browser/quota/quota_internals_ui.cc index aa216a5..54d4e90 100644 --- a/content/browser/quota/quota_internals_ui.cc +++ b/content/browser/quota/quota_internals_ui.cc
@@ -17,8 +17,9 @@ namespace content { QuotaInternalsUI::QuotaInternalsUI(WebUI* web_ui) : WebUIController(web_ui) { - WebUIDataSource* source = - WebUIDataSource::Create(kChromeUIQuotaInternalsHost); + WebUIDataSource* source = WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), + kChromeUIQuotaInternalsHost); source->AddResourcePaths( base::make_span(kQuotaInternalsResources, kQuotaInternalsResourcesSize)); @@ -28,9 +29,6 @@ source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self';"); - - WebContents* web_contents = web_ui->GetWebContents(); - WebUIDataSource::Add(web_contents->GetBrowserContext(), source); } WEB_UI_CONTROLLER_TYPE_IMPL(QuotaInternalsUI) @@ -44,4 +42,4 @@ static_cast<RenderFrameHostImpl*>(render_frame_host)->EnableMojoJsBindings(); } -} // namespace content \ No newline at end of file +} // namespace content
diff --git a/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc b/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc index 7086053..4827e8f 100644 --- a/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc +++ b/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc
@@ -73,6 +73,8 @@ kNo_UnloadHandlerExistsOnSameSiteNavigation: return "BI not swapped - unload handler exists and the navigation is " "same-site"; + case ShouldSwapBrowsingInstance::kNo_NotPrimaryMainFrame: + return "BI not swapped - not a primary main frame"; } }
diff --git a/content/browser/renderer_host/back_forward_cache_metrics.cc b/content/browser/renderer_host/back_forward_cache_metrics.cc index adffc37..72bc561f 100644 --- a/content/browser/renderer_host/back_forward_cache_metrics.cc +++ b/content/browser/renderer_host/back_forward_cache_metrics.cc
@@ -532,6 +532,7 @@ case ShouldSwapBrowsingInstance::kNo_HasNotComittedAnyNavigation: case ShouldSwapBrowsingInstance:: kNo_UnloadHandlerExistsOnSameSiteNavigation: + case ShouldSwapBrowsingInstance::kNo_NotPrimaryMainFrame: return false; case ShouldSwapBrowsingInstance::kYes_ForceSwap: case ShouldSwapBrowsingInstance::kYes_CrossSiteProactiveSwap:
diff --git a/content/browser/renderer_host/document_service_browsertest.cc b/content/browser/renderer_host/document_service_browsertest.cc index c1e8af73..d312ec0 100644 --- a/content/browser/renderer_host/document_service_browsertest.cc +++ b/content/browser/renderer_host/document_service_browsertest.cc
@@ -8,6 +8,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_features.h" +#include "content/public/test/back_forward_cache_util.h" #include "content/public/test/browser_test.h" #include "content/public/test/content_browser_test.h" #include "content/public/test/content_browser_test_utils.h" @@ -66,6 +67,11 @@ NotClosedInPrerenderingActivation) { const GURL kInitialUrl = embedded_test_server()->GetURL("/empty.html"); const GURL kPrerenderingUrl = embedded_test_server()->GetURL("/title1.html"); + // The test assumes documents and their DocumentServices get deleted after + // non-activation navigations. To ensure this, disable back/forward cache. + DisableBackForwardCacheForTesting( + shell()->web_contents(), + content::BackForwardCache::TEST_REQUIRES_NO_CACHING); // Navigate to an initial page. ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl)); @@ -73,10 +79,6 @@ int host_id = prerender_helper()->AddPrerender(kPrerenderingUrl); RenderFrameHost* prerendered_frame_host = prerender_helper()->GetPrerenderedMainFrameHost(host_id); - // We should disable proactive BrowsingInstance swap for the navigation below - // to ensure that the speculative RFH is going to use the same - // BrowsingInstance as the original RFH and it's not replaced on navigation. - DisableProactiveBrowsingInstanceSwapFor(prerendered_frame_host); mojo::Remote<mojom::Echo> echo_remote; bool echo_deleted = false;
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc index d0401bf..af6b364 100644 --- a/content/browser/renderer_host/navigation_request.cc +++ b/content/browser/renderer_host/navigation_request.cc
@@ -313,9 +313,18 @@ return true; } +bool DoesHeaderContainClientHint( + const net::HttpRequestHeaders& headers, + const network::mojom::WebClientHintsType hint) { + std::string header = network::GetClientHintToNameMap().at(hint); + std::string value; + return headers.GetHeader(header, &value) && value == "?1"; +} + // Computes the value that should be set for the User-Agent header, based on the -// values of relevant headers like Sec-CH-UA-Reduced. If `user_agent_override` -// is non-empty, `user_agent_override` is returned as the header value. +// values of relevant headers like Sec-CH-UA-Reduced or Sec-CH-UA-Full. If +// `user_agent_override` is non-empty, `user_agent_override` is returned as the +// header value. std::string ComputeUserAgentValue(const net::HttpRequestHeaders& headers, const std::string& user_agent_override, content::BrowserContext* context) { @@ -325,13 +334,23 @@ return user_agent_override; } + // If Sec-CH-UA-Full is set on the headers, it means that the token for the + // SendFullUserAgentAfterReduction Origin Trial has been validated and we + // should send a reduced UA string on the request. + const bool full = DoesHeaderContainClientHint( + headers, network::mojom::WebClientHintsType::kFullUserAgent); + + if (full) { + base::UmaHistogramEnumeration("Navigation.UserAgentStringType", + UserAgentStringType::kFullVersion); + return GetContentClient()->browser()->GetFullUserAgent(); + } + // If Sec-CH-UA-Reduced is set on the headers, it means that the token for the // UserAgentReduction Origin Trial has been validated and we should send a // reduced UA string on the request. - std::string header = network::GetClientHintToNameMap().at( - network::mojom::WebClientHintsType::kUAReduced); - std::string value; - const bool reduced = headers.GetHeader(header, &value) && value == "?1"; + const bool reduced = DoesHeaderContainClientHint( + headers, network::mojom::WebClientHintsType::kUAReduced); base::UmaHistogramEnumeration("Navigation.UserAgentStringType", reduced ? UserAgentStringType::kReducedVersion : UserAgentStringType::kFullVersion); @@ -868,26 +887,36 @@ } // If the response does not contain an Accept-CH header, then remove the -// Sec-CH-UA-Reduced client hint from the Accept-CH cache, if it exists, for the -// response origin. The `client_hints` vector also has kUaReduced removed from -// it if the Accept-CH response header doesn't exist. -void RemoveUaReducedFromAcceptCH( +// Sec-CH-UA-Reduced or Sec-CH-UA-Full client hint from the Accept-CH cache, if +// it exists, for the response origin. The `client_hints` vector also has +// kUaReduced or kFullUserAgent removed from it if the Accept-CH response header +// doesn't exist. +void RemoveUaReducedAndFullFromAcceptCH( const GURL& url, ClientHintsControllerDelegate* delegate, const network::mojom::URLResponseHead* response, std::vector<network::mojom::WebClientHintsType>& client_hints) { - if (response && !response->parsed_headers->accept_ch && - base::Contains(client_hints, - network::mojom::WebClientHintsType::kUAReduced)) { - // For Chrome to continue to send Sec-CH-UA-Reduced, the server must - // continue replying with: + if (response && !response->parsed_headers->accept_ch) { + // For Chrome to continue to send Sec-CH-UA-Reduced or Sec-CH-UA-Full, the + // server must continue replying with: // - a valid Origin Trial token. - // - Accept-CH header with Sec-CH-UA-Reduced as a value. + // - Accept-CH header with Sec-CH-UA-Reduced or Sec-CH-UA-Full as a value. // // Here, it did not. So it gets removed from the persisted client hints // for the next request. - base::Erase(client_hints, network::mojom::WebClientHintsType::kUAReduced); - PersistAcceptCH(url, delegate, client_hints); + std::vector<network::mojom::WebClientHintsType> hints_to_remove = { + network::mojom::WebClientHintsType::kUAReduced, + network::mojom::WebClientHintsType::kFullUserAgent}; + bool need_update_storage = false; + for (const auto& hint : hints_to_remove) { + if (base::Contains(client_hints, hint)) { + base::Erase(client_hints, hint); + need_update_storage = true; + } + } + if (need_update_storage) { + PersistAcceptCH(url, delegate, client_hints); + } } } @@ -3963,17 +3992,18 @@ source_url, response_head->parsed_headers, response_head->headers.get(), browser_context, client_hints_delegate, frame_tree_node_); // CriticalClientHintsThrottle issues a 307 internal redirect without the - // original headers, and we don't want to remove Sec-CH-UA-Reduced when - // Critical-CH is set. This means that if the site sends a 307 (instead of - // a 301 or 302), Sec-CH-UA-Reduced will *not* be removed from the Accept-CH - // cache if the Accept-CH header is missing from the redirect response. + // original headers, and we don't want to remove Sec-CH-UA-Reduced or + // Sec-CH-UA-Full when Critical-CH is set. This means that if the site + // sends a 307 (instead of a 301 or 302), Sec-CH-UA-Reduced or + // Sec-CH-UA-Full will *not* be removed from the Accept-CH cache if the + // Accept-CH header is missing from the redirect response. if (response_head->headers && response_head->headers->response_code() != net::HTTP_TEMPORARY_REDIRECT) { std::vector<network::mojom::WebClientHintsType> client_hints = LookupAcceptCHForCommit(source_url, client_hints_delegate, frame_tree_node_); - RemoveUaReducedFromAcceptCH(source_url, client_hints_delegate, - response_head, client_hints); + RemoveUaReducedAndFullFromAcceptCH(source_url, client_hints_delegate, + response_head, client_hints); } AddNavigationRequestClientHintsHeaders( @@ -4379,9 +4409,9 @@ } commit_params_->enabled_client_hints = LookupAcceptCHForCommit( common_params_->url, client_hints_delegate, frame_tree_node_); - RemoveUaReducedFromAcceptCH(common_params_->url, client_hints_delegate, - response(), - commit_params_->enabled_client_hints); + RemoveUaReducedAndFullFromAcceptCH(common_params_->url, + client_hints_delegate, response(), + commit_params_->enabled_client_hints); } // Generate a UKM source and track it on NavigationRequest. This will be
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc index d1b05af..f8bdad0 100644 --- a/content/browser/renderer_host/render_frame_host_impl.cc +++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -11628,18 +11628,19 @@ // DidCommitProvisionalLoadParams to DidCommitSameDocumentNavigationParams. // For other navigations, the CommonNavigationParams' value supplied by the // browser to the renderer at commit time can be used, as the renderer will - // always follow it. - // Note: We will always replace the initial NavigationEntry (CommonParams' - // should_replace_current_entry will be true) but the renderer doesn't know - // about it so DidCommitParams' should_replace_current_entry might differ, - // which is why we depend on the DidCommitParams for that case (for now). + // always follow it. An exception is when on the initial NavigationEntry, + // CommonParams' should_replace_current_entry will always be true on the + // browser side but the renderer might not know about it so DidCommitParams' + // should_replace_current_entry might differ, which is why we "skip" comparing + // for browser vs renderer values in that case, by comparing the renderer + // value against itself (through returning DidCommitParams' + // should_replace_current_entry here). NavigationEntryImpl* last_entry = request->frame_tree_node() ->navigator() .controller() .GetLastCommittedEntry(); return (request->IsSameDocument() || - (request->IsInMainFrame() && last_entry && - last_entry->IsInitialEntry())) + (last_entry && last_entry->IsInitialEntry())) ? params.should_replace_current_entry : request->common_params().should_replace_current_entry; }
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc index 2e9fb06..b6e4b529 100644 --- a/content/browser/renderer_host/render_frame_host_manager.cc +++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -253,6 +253,9 @@ kNo_UnloadHandlerExistsOnSameSiteNavigation: return ProtoLevel:: SHOULD_SWAP_BROWSING_INSTANCE_NO_UNLOAD_HANDLER_EXISTS_ON_SAME_SITE_NAVIGATION; + case ShouldSwapBrowsingInstance::kNo_NotPrimaryMainFrame: + return ProtoLevel:: + SHOULD_SWAP_BROWSING_INSTANCE_NO_NOT_PRIMARY_MAIN_FRAME; } } @@ -1670,9 +1673,9 @@ !IsBackForwardCacheEnabled()) return ShouldSwapBrowsingInstance::kNo_ProactiveSwapDisabled; - // Only main frames are eligible to swap BrowsingInstances. - if (!frame_tree_node_->IsMainFrame()) - return ShouldSwapBrowsingInstance::kNo_NotMainFrame; + // Only primary main frames are eligible to swap BrowsingInstances. + if (frame_tree_node_->GetFrameType() != FrameType::kPrimaryMainFrame) + return ShouldSwapBrowsingInstance::kNo_NotPrimaryMainFrame; // If the frame has not committed any navigation yet, we should not try to do // a proactive swap.
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc index 9181312..ec417459 100644 --- a/content/browser/renderer_host/render_process_host_impl.cc +++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -5060,14 +5060,12 @@ } // Pass bits of global renderer state to the renderer. - GetRendererInterface()->SetUserAgent( + GetRendererInterface()->InitializeRenderer( GetContentClient()->browser()->GetUserAgentBasedOnPolicy( - browser_context_)); - GetRendererInterface()->SetReducedUserAgent( - GetContentClient()->browser()->GetReducedUserAgent()); - GetRendererInterface()->SetUserAgentMetadata( - GetContentClient()->browser()->GetUserAgentMetadata()); - GetRendererInterface()->SetCorsExemptHeaderList( + browser_context_), + GetContentClient()->browser()->GetFullUserAgent(), + GetContentClient()->browser()->GetReducedUserAgent(), + GetContentClient()->browser()->GetUserAgentMetadata(), storage_partition_impl_->cors_exempt_header_list()); NotifyRendererOfLockedStateUpdate();
diff --git a/content/browser/renderer_host/should_swap_browsing_instance.h b/content/browser/renderer_host/should_swap_browsing_instance.h index 4a0b5d6..49309f7 100644 --- a/content/browser/renderer_host/should_swap_browsing_instance.h +++ b/content/browser/renderer_host/should_swap_browsing_instance.h
@@ -37,8 +37,9 @@ kNo_Guest = 18, kNo_HasNotComittedAnyNavigation = 19, kNo_UnloadHandlerExistsOnSameSiteNavigation = 20, + kNo_NotPrimaryMainFrame = 21, - kMaxValue = kNo_UnloadHandlerExistsOnSameSiteNavigation + kMaxValue = kNo_NotPrimaryMainFrame }; } // namespace content
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc index 602ba20..a73701b6 100644 --- a/content/browser/service_worker/service_worker_browsertest.cc +++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -235,10 +235,9 @@ return std::move(http_response); } -void CountScriptResources( - ServiceWorkerContextWrapper* wrapper, - const GURL& scope, - int* num_resources) { +void CountScriptResources(ServiceWorkerContextWrapper* wrapper, + const GURL& scope, + int* num_resources) { *num_resources = -1; std::vector<ServiceWorkerRegistrationInfo> infos = @@ -376,6 +375,12 @@ EXPECT_FALSE(net::IsCertStatusError(entry->GetSSL().cert_status)); } +enum class UserAgentOriginTrialTestType { + UAReduction, + UADeprecation, + UAReductionAndDeprecation +}; + } // namespace class ServiceWorkerBrowserTest : public ContentBrowserTest { @@ -1136,7 +1141,7 @@ class UserAgentServiceWorkerBrowserTest : public ServiceWorkerBrowserTest, - public testing::WithParamInterface<bool> { + public testing::WithParamInterface<UserAgentOriginTrialTestType> { public: void SetUpCommandLine(base::CommandLine* command_line) override { // The public key for the default privatey key used by the @@ -1147,13 +1152,11 @@ kOriginTrialTestPublicKey); } - bool WithUserAgentReductionOriginTrialToken() const { return GetParam(); } - std::string GetExpectedUserAgent() const { ShellContentBrowserClient* client = ShellContentBrowserClient::Get(); - if (WithUserAgentReductionOriginTrialToken()) + if (GetParam() == UserAgentOriginTrialTestType::UAReduction) return client->GetReducedUserAgent(); - return client->GetUserAgent(); + return client->GetFullUserAgent(); } }; @@ -1165,12 +1168,22 @@ // Generated by running (in tools/origin_trials): // generate_token.py https://127.0.0.1:44444 UserAgentReduction // --expire-timestamp=2000000000 - static constexpr char kOriginTrialToken[] = + static constexpr char kUAReducedOriginTrialToken[] = "A93QtcQ0CRKf5ioPasUwNbweXQWgbI4ZEshiz+" "YS7dkQEWVfW9Ua2pTnA866sZwRzuElkPwsUdGdIaW0fRUP8AwAAABceyJvcmlnaW4iOiAiaH" "R0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAiZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb2" "4iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0="; + // Generated by running (in tools/origin_trials): + // generate_token.py https://127.0.0.1:44444 SendFullUserAgentAfterReduction + // --expire-timestamp=2000000000 + static constexpr char kUAFullOriginTrialToken[] = + "A6+Ti/9KuXTgmFzOQwkTuO8k0QFH8vUaxmv0CllAET1/" + "307KShF6fhskMuBqFUvqO7ViAkZ+" + "NSeJhQI0n5aLggsAAABpeyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAi" + "ZmVhdHVyZSI6ICJTZW5kRnVsbFVzZXJBZ2VudEFmdGVyUmVkdWN0aW9uIiwgImV4cGlyeSI6" + "IDIwMDAwMDAwMDB9"; + const GURL main_page_url( base::StrCat({kOriginUrl, "/create_service_worker.html"})); const GURL service_worker_url(base::StrCat({kOriginUrl, "/user_agent.js"})); @@ -1196,10 +1209,25 @@ ? "javascript" : "html", "\n"}); - if (WithUserAgentReductionOriginTrialToken() && - params->url_request.url == service_worker_url) { - base::StrAppend(&headers, - {"Origin-Trial: ", kOriginTrialToken, "\n"}); + if (params->url_request.url == service_worker_url) { + switch (GetParam()) { + case UserAgentOriginTrialTestType::UAReduction: + base::StrAppend( + &headers, + {"Origin-Trial: ", kUAReducedOriginTrialToken, "\n"}); + break; + case UserAgentOriginTrialTestType::UADeprecation: + base::StrAppend( + &headers, {"Origin-Trial: ", kUAFullOriginTrialToken, "\n"}); + break; + case UserAgentOriginTrialTestType::UAReductionAndDeprecation: + base::StrAppend( + &headers, {"Origin-Trial: ", kUAReducedOriginTrialToken, ",", + kUAFullOriginTrialToken, "\n"}); + break; + default: + break; + } } URLLoaderInterceptor::WriteResponse(path, params->client.get(), @@ -1236,9 +1264,12 @@ run_loop.Run(); } -INSTANTIATE_TEST_SUITE_P(All, - UserAgentServiceWorkerBrowserTest, - testing::Bool()); +INSTANTIATE_TEST_SUITE_P( + All, + UserAgentServiceWorkerBrowserTest, + testing::Values(UserAgentOriginTrialTestType::UAReduction, + UserAgentOriginTrialTestType::UADeprecation, + UserAgentOriginTrialTestType::UAReductionAndDeprecation)); class ServiceWorkerEagerCacheStorageSetupTest : public ServiceWorkerBrowserTest {
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index ae83b91c..e025a616 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -174,6 +174,15 @@ ServiceWorkerContext::ResultCallback callback_; }; +void RunOrPostTaskOnUIThread(const base::Location& location, + base::OnceClosure task) { + if (BrowserThread::CurrentlyOn(BrowserThread::UI)) { + std::move(task).Run(); + } else { + GetUIThreadTaskRunner({})->PostTask(location, std::move(task)); + } +} + } // namespace @@ -675,7 +684,6 @@ const blink::StorageKey& key, blink::TransferableMessage message, ResultCallback result_callback) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); // Ensure the callback is called asynchronously. auto wrapped_callback = base::BindOnce( [](ResultCallback callback, bool success) { @@ -684,12 +692,44 @@ }, std::move(result_callback)); + // TODO(https://crbug.com/1295029): Don't post task to the UI thread. Instead, + // make all call sites run on the UI thread. + RunOrPostTaskOnUIThread( + FROM_HERE, + base::BindOnce(&ServiceWorkerContextWrapper:: + StartServiceWorkerAndDispatchMessageOnUIThread, + this, scope, key, std::move(message), + base::BindOnce( + [](ResultCallback callback, + scoped_refptr<base::TaskRunner> callback_runner, + bool success) { + callback_runner->PostTask( + FROM_HERE, + base::BindOnce(std::move(callback), success)); + }, + std::move(wrapped_callback), + base::ThreadTaskRunnerHandle::Get()))); +} + +void ServiceWorkerContextWrapper:: + StartServiceWorkerAndDispatchMessageOnUIThread( + const GURL& scope, + const blink::StorageKey& key, + blink::TransferableMessage message, + ResultCallback result_callback) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + + if (!context_core_) { + std::move(result_callback).Run(/*success=*/false); + return; + } + FindRegistrationForScopeImpl( net::SimplifyUrlForRequest(scope), key, /*include_installing_version=*/false, base::BindOnce( &ServiceWorkerContextWrapper::DidFindRegistrationForMessageDispatch, - this, std::move(message), scope, std::move(wrapped_callback))); + this, std::move(message), scope, std::move(result_callback))); } void ServiceWorkerContextWrapper::DidFindRegistrationForMessageDispatch(
diff --git a/content/browser/service_worker/service_worker_internals_ui.cc b/content/browser/service_worker/service_worker_internals_ui.cc index 84544e2..d5615a6 100644 --- a/content/browser/service_worker/service_worker_internals_ui.cc +++ b/content/browser/service_worker/service_worker_internals_ui.cc
@@ -326,8 +326,9 @@ ServiceWorkerInternalsUI::ServiceWorkerInternalsUI(WebUI* web_ui) : WebUIController(web_ui) { - WebUIDataSource* source = - WebUIDataSource::Create(kChromeUIServiceWorkerInternalsHost); + WebUIDataSource* source = WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), + kChromeUIServiceWorkerInternalsHost); source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); @@ -343,9 +344,6 @@ source->DisableDenyXFrameOptions(); web_ui->AddMessageHandler(std::make_unique<ServiceWorkerInternalsHandler>()); - BrowserContext* browser_context = - web_ui->GetWebContents()->GetBrowserContext(); - WebUIDataSource::Add(browser_context, source); } ServiceWorkerInternalsUI::~ServiceWorkerInternalsUI() = default;
diff --git a/content/browser/service_worker/service_worker_version.cc b/content/browser/service_worker/service_worker_version.cc index 40eeefd..36ec087 100644 --- a/content/browser/service_worker/service_worker_version.cc +++ b/content/browser/service_worker/service_worker_version.cc
@@ -1051,8 +1051,8 @@ void ServiceWorkerVersion::SetValidOriginTrialTokens( const blink::TrialTokenValidator::FeatureToTokensMap& tokens) { - origin_trial_tokens_ = validator_.GetValidTokens( - url::Origin::Create(scope()), tokens, clock_->Now()); + origin_trial_tokens_ = + validator_.GetValidTokens(key_.origin(), tokens, clock_->Now()); } void ServiceWorkerVersion::SetDevToolsAttached(bool attached) { @@ -1105,8 +1105,7 @@ // wasn't set in the entry. if (!origin_trial_tokens_) { origin_trial_tokens_ = validator_.GetValidTokensFromHeaders( - url::Origin::Create(scope()), main_script_response_->headers.get(), - clock_->Now()); + key_.origin(), main_script_response_->headers.get(), clock_->Now()); } if (context_) { @@ -1887,11 +1886,16 @@ outside_fetch_client_settings_object_.Clone(); ContentBrowserClient* browser_client = GetContentClient()->browser(); - params->user_agent = (origin_trial_tokens_ && - origin_trial_tokens_->contains("UserAgentReduction")) - ? browser_client->GetReducedUserAgent() - : browser_client->GetUserAgentBasedOnPolicy( - context_->wrapper()->browser_context()); + if (origin_trial_tokens_ && + origin_trial_tokens_->contains("SendFullUserAgentAfterReduction")) { + params->user_agent = browser_client->GetFullUserAgent(); + } else if (origin_trial_tokens_ && + origin_trial_tokens_->contains("UserAgentReduction")) { + params->user_agent = browser_client->GetReducedUserAgent(); + } else { + params->user_agent = browser_client->GetUserAgentBasedOnPolicy( + context_->wrapper()->browser_context()); + } params->ua_metadata = browser_client->GetUserAgentMetadata(); params->is_installed = IsInstalled(status_); params->script_url_to_skip_throttling = updated_script_url_;
diff --git a/content/browser/speech/tts_win.cc b/content/browser/speech/tts_win.cc index 24c9be4..4312fd72 100644 --- a/content/browser/speech/tts_win.cc +++ b/content/browser/speech/tts_win.cc
@@ -310,8 +310,7 @@ if (paused_) Resume(); - DCHECK(is_speaking_); - DCHECK_NE(utterance_id_, kInvalidUtteranceId); + DCHECK(is_speaking_ || (utterance_id_ == kInvalidUtteranceId)); is_speaking_ = false; utterance_id_ = kInvalidUtteranceId; } @@ -616,7 +615,13 @@ base::OnceCallback<void(bool)> on_speak_finished, bool success) { DCHECK(BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - DCHECK(is_speaking_); + DCHECK(is_speaking_ || (utterance_id_ == kInvalidUtteranceId)); + // If speech was stopped while we were processing the utterance (For example, + // in the case of a page navigation), then there is nothing left to do. Do not + // emit an asynchronous TTS event to confirm the end of speech. + if (!is_speaking_) { + return; + } // If the utterance was not able to be emitted, stop the speaking. There // won't be any asynchronous TTS event to confirm the end of the speech.
diff --git a/content/browser/tracing/tracing_ui.cc b/content/browser/tracing/tracing_ui.cc index 7a12f06..57d17e8 100644 --- a/content/browser/tracing/tracing_ui.cc +++ b/content/browser/tracing/tracing_ui.cc
@@ -236,10 +236,8 @@ : WebUIController(web_ui), delegate_(GetContentClient()->browser()->GetTracingDelegate()) { // Set up the chrome://tracing/ source. - BrowserContext* browser_context = - web_ui->GetWebContents()->GetBrowserContext(); - - WebUIDataSource* source = WebUIDataSource::Create(kChromeUITracingHost); + WebUIDataSource* source = WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), kChromeUITracingHost); source->DisableTrustedTypesCSP(); source->UseStringsJs(); source->SetDefaultResource(IDR_TRACING_ABOUT_TRACING_HTML); @@ -247,7 +245,6 @@ source->SetRequestFilter(base::BindRepeating(OnShouldHandleRequest), base::BindRepeating(OnTracingRequest)); - WebUIDataSource::Add(browser_context, source); } TracingUI::~TracingUI() = default;
diff --git a/content/browser/web_contents/web_contents_view_android.cc b/content/browser/web_contents/web_contents_view_android.cc index fdc564b1..adc7fd1 100644 --- a/content/browser/web_contents/web_contents_view_android.cc +++ b/content/browser/web_contents/web_contents_view_android.cc
@@ -39,6 +39,7 @@ #include "ui/events/android/key_event_android.h" #include "ui/events/android/motion_event_android.h" #include "ui/gfx/android/java_bitmap.h" +#include "ui/gfx/android/view_configuration.h" #include "ui/gfx/image/image_skia.h" using base::android::AttachCurrentThread; @@ -49,6 +50,15 @@ namespace { +// Returns the minimum distance in DIPs, for drag event being considered as an +// intentional drag. +float DragMovementThresholdDip() { + static float radius = base::GetFieldTrialParamByFeatureAsDouble( + features::kDragAndDrop, features::kDragAndDropMovementThresholdDipParam, + /*default_value=*/gfx::ViewConfiguration::GetTouchSlopInDips()); + return radius; +} + // True if we want to disable Android native event batching and use // compositor event queue. bool ShouldRequestUnbufferedDispatch() { @@ -59,11 +69,15 @@ return should_request_unbuffered_dispatch; } -bool IsDragEnabledForDropData(const DropData& drop_data) { +bool IsDragAndDropEnabled() { // Cache the feature flag value so it isn't queried on every drag start. static const bool drag_feature_enabled = base::FeatureList::IsEnabled(features::kDragAndDrop); - if (!drag_feature_enabled) { + return drag_feature_enabled; +} + +bool IsDragEnabledForDropData(const DropData& drop_data) { + if (!IsDragAndDropEnabled()) { return drop_data.text.has_value(); } return !drop_data.url.is_empty() || !drop_data.file_contents.empty() || @@ -275,6 +289,9 @@ void WebContentsViewAndroid::ShowContextMenu(RenderFrameHost& render_frame_host, const ContextMenuParams& params) { + if (is_active_drag_ && drag_exceeded_movement_threshold_) + return; + auto* rwhv = static_cast<RenderWidgetHostViewAndroid*>( web_contents_->GetRenderWidgetHostView()); @@ -430,6 +447,24 @@ drag_location_ = location; drag_screen_location_ = screen_location; + // When drag and drop is enabled, attempt to dismiss the context menu if drag + // leaves start location. + if (IsDragAndDropEnabled()) { + // On Android DragEvent.ACTION_DRAG_ENTER does not have a valid location. + // See https://developer.android.com/guide/topics/ui/drag-drop#table2. + if (!is_active_drag_) { + is_active_drag_ = true; + drag_entered_location_ = location; + } else if (!drag_exceeded_movement_threshold_) { + float radius = DragMovementThresholdDip(); + if (!drag_location_.IsWithinDistance(drag_entered_location_, radius)) { + drag_exceeded_movement_threshold_ = true; + if (delegate_) + delegate_->DismissContextMenu(); + } + } + } + blink::DragOperationsMask allowed_ops = static_cast<blink::DragOperationsMask>(blink::kDragOperationCopy | blink::kDragOperationMove); @@ -469,6 +504,9 @@ base::DoNothing()); OnSystemDragEnded(); + is_active_drag_ = false; + drag_exceeded_movement_threshold_ = false; + drag_entered_location_ = gfx::PointF(); drag_location_ = gfx::PointF(); drag_screen_location_ = gfx::PointF(); }
diff --git a/content/browser/web_contents/web_contents_view_android.h b/content/browser/web_contents/web_contents_view_android.h index 5c50516..ec22cb0 100644 --- a/content/browser/web_contents/web_contents_view_android.h +++ b/content/browser/web_contents/web_contents_view_android.h
@@ -178,6 +178,14 @@ // Show/hide popup UI for <select> tag. std::unique_ptr<SelectPopup> select_popup_; + // Whether drag went beyond the movement threshold to be considered as an + // intentional drag. If true, ::ShowContextMenu will be ignored. + bool drag_exceeded_movement_threshold_ = false; + // Whether there's an active drag process. + bool is_active_drag_ = false; + // The first drag location during a specific drag process. + gfx::PointF drag_entered_location_; + gfx::PointF drag_location_; gfx::PointF drag_screen_location_; };
diff --git a/content/browser/webid/federated_auth_request_impl.cc b/content/browser/webid/federated_auth_request_impl.cc index 244c1e0b..5becd25 100644 --- a/content/browser/webid/federated_auth_request_impl.cc +++ b/content/browser/webid/federated_auth_request_impl.cc
@@ -22,6 +22,7 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/web_contents.h" #include "content/public/common/content_client.h" +#include "third_party/blink/public/mojom/devtools/console_message.mojom.h" #include "third_party/blink/public/mojom/devtools/inspector_issue.mojom.h" #include "ui/accessibility/ax_mode.h" #include "url/url_constants.h" @@ -85,6 +86,77 @@ return query; } +std::string GetConsoleErrorMessage(RequestIdTokenStatus status) { + switch (status) { + case RequestIdTokenStatus::kApprovalDeclined: { + return "User declined the sign-in attempt."; + } + case RequestIdTokenStatus::kErrorTooManyRequests: { + return "Only one navigator.credentials.get request may be outstanding at " + "one time."; + } + case RequestIdTokenStatus::kErrorFetchingWellKnownHttpNotFound: { + return "The provider's .well-known configuration cannot be found."; + } + case RequestIdTokenStatus::kErrorFetchingWellKnownNoResponse: { + return "The response body is empty when fetching the provider's " + ".well-known configuration."; + } + case RequestIdTokenStatus::kErrorFetchingWellKnownInvalidResponse: { + return "Provider's .well-known configuration is invalid."; + } + case RequestIdTokenStatus::kErrorFetchingClientIdMetadataHttpNotFound: { + return "The provider's client metadata endpoint cannot be found."; + } + case RequestIdTokenStatus::kErrorFetchingClientIdMetadataNoResponse: { + return "The response body is empty when fetching the provider's client " + "metadata."; + } + case RequestIdTokenStatus::kErrorFetchingClientIdMetadataInvalidResponse: { + return "Provider's client metadata is invalid."; + } + case RequestIdTokenStatus::kErrorFetchingSignin: { + return "Error attempting to reach the provider's sign-in endpoint."; + } + case RequestIdTokenStatus::kErrorInvalidSigninResponse: { + return "Provider's sign-in response is invalid."; + } + case RequestIdTokenStatus::kErrorFetchingAccountsHttpNotFound: { + return "The provider's accounts list endpoint cannot be found."; + } + case RequestIdTokenStatus::kErrorFetchingAccountsNoResponse: { + return "The response body is empty when fetching the provider's accounts " + "list."; + } + case RequestIdTokenStatus::kErrorFetchingAccountsInvalidResponse: { + return "Provider's accounts list is invalid."; + } + case RequestIdTokenStatus::kErrorFetchingIdTokenHttpNotFound: { + return "The provider's id token endpoint cannot be found."; + } + case RequestIdTokenStatus::kErrorFetchingIdTokenNoResponse: { + return "The response body is empty when fetching the provider's id " + "token."; + } + case RequestIdTokenStatus::kErrorFetchingIdTokenInvalidResponse: { + return "Provider's id token is invalid."; + } + case RequestIdTokenStatus::kErrorFetchingIdTokenInvalidRequest: { + return "The id token fetching request is invalid."; + } + case RequestIdTokenStatus::kErrorCanceled: { + return "The request has been aborted."; + } + case RequestIdTokenStatus::kError: { + return "Error retrieving an id token."; + } + case RequestIdTokenStatus::kSuccess: { + DCHECK(false); + return ""; + } + } +} + } // namespace FederatedAuthRequestImpl::FederatedAuthRequestImpl(RenderFrameHost* host, @@ -891,6 +963,7 @@ // an error, so it would be cleaner to do this by reporting the inspector // issue from the browser. AddInspectorIssue(status); + AddConsoleErrorMessage(status); } CleanUp(); @@ -936,6 +1009,13 @@ std::move(details))); } +void FederatedAuthRequestImpl::AddConsoleErrorMessage( + RequestIdTokenStatus status) { + std::string message = GetConsoleErrorMessage(status); + render_frame_host_->AddMessageToConsole( + blink::mojom::ConsoleMessageLevel::kError, message); +} + void FederatedAuthRequestImpl::CompleteLogoutRequest( blink::mojom::LogoutStatus status) { network_manager_.reset();
diff --git a/content/browser/webid/federated_auth_request_impl.h b/content/browser/webid/federated_auth_request_impl.h index 7ebd1f81c..85ac755 100644 --- a/content/browser/webid/federated_auth_request_impl.h +++ b/content/browser/webid/federated_auth_request_impl.h
@@ -123,6 +123,14 @@ // the Issues panel in DevTools. void AddInspectorIssue(blink::mojom::RequestIdTokenStatus status); + // Adds a console error message related to a federated authentication request + // issue. The Issues panel is preferred, but for now we also surface console + // error messages since it is much simpler to add. + // TODO(crbug.com/1294415): When the FedCM API is more stable, we should + // ensure that the Issues panel contains all of the needed debugging + // information and then we can remove the console error messages. + void AddConsoleErrorMessage(blink::mojom::RequestIdTokenStatus status); + const raw_ptr<RenderFrameHost> render_frame_host_ = nullptr; const url::Origin origin_;
diff --git a/content/browser/webid/federated_auth_request_impl_unittest.cc b/content/browser/webid/federated_auth_request_impl_unittest.cc index 6be46ce..fa6f7cc 100644 --- a/content/browser/webid/federated_auth_request_impl_unittest.cc +++ b/content/browser/webid/federated_auth_request_impl_unittest.cc
@@ -861,6 +861,39 @@ EXPECT_EQ(main_test_rfh()->GetFederatedAuthRequestIssueCount( test_case.expected.devtools_issue_status), auth_response.first == RequestIdTokenStatus::kSuccess ? 0 : 1); + static std::unordered_map<RequestIdTokenStatus, absl::optional<std::string>> + status_to_message = { + {RequestIdTokenStatus::kSuccess, absl::nullopt}, + {RequestIdTokenStatus::kApprovalDeclined, + "User declined the sign-in attempt."}, + {RequestIdTokenStatus::kErrorFetchingWellKnownHttpNotFound, + "The provider's .well-known configuration cannot be found."}, + {RequestIdTokenStatus::kErrorFetchingWellKnownNoResponse, + "The response body is empty when fetching the provider's " + ".well-known " + "configuration."}, + {RequestIdTokenStatus::kErrorFetchingWellKnownInvalidResponse, + "Provider's .well-known configuration is invalid."}, + {RequestIdTokenStatus::kErrorFetchingSignin, + "Error attempting to reach the provider's sign-in endpoint."}, + {RequestIdTokenStatus::kErrorInvalidSigninResponse, + "Provider's sign-in response is invalid."}, + {RequestIdTokenStatus::kError, "Error retrieving an id token."}, + {RequestIdTokenStatus::kErrorFetchingAccountsNoResponse, + "The response body is empty when fetching the provider's accounts " + "list."}, + {RequestIdTokenStatus::kErrorFetchingAccountsInvalidResponse, + "Provider's accounts list is invalid."}}; + std::vector<std::string> messages = + RenderFrameHostTester::For(main_rfh())->GetConsoleMessages(); + absl::optional<std::string> expected_message = + status_to_message[test_case.expected.devtools_issue_status]; + if (!expected_message) { + EXPECT_EQ(0u, messages.size()); + } else { + ASSERT_EQ(1u, messages.size()); + EXPECT_EQ(expected_message.value(), messages[0]); + } } // Test Logout method success with multiple relying parties.
diff --git a/content/browser/webid/idp_network_request_manager.cc b/content/browser/webid/idp_network_request_manager.cc index debb3701..8e610c4 100644 --- a/content/browser/webid/idp_network_request_manager.cc +++ b/content/browser/webid/idp_network_request_manager.cc
@@ -872,7 +872,6 @@ CreateTrafficAnnotation(); auto resource_request = std::make_unique<network::ResourceRequest>(); - const url::Origin& idp_origin = url::Origin::Create(provider_); resource_request->url = target_url; resource_request->credentials_mode = network::mojom::CredentialsMode::kOmit; @@ -891,8 +890,7 @@ resource_request->request_initiator = relying_party_origin_; resource_request->trusted_params = network::ResourceRequest::TrustedParams(); resource_request->trusted_params->isolation_info = - net::IsolationInfo::Create(net::IsolationInfo::RequestType::kOther, - idp_origin, idp_origin, net::SiteForCookies()); + net::IsolationInfo::CreateTransient(); return network::SimpleURLLoader::Create(std::move(resource_request), traffic_annotation);
diff --git a/content/browser/webui/web_ui_data_source_impl.cc b/content/browser/webui/web_ui_data_source_impl.cc index eda0259..a9dee16b 100644 --- a/content/browser/webui/web_ui_data_source_impl.cc +++ b/content/browser/webui/web_ui_data_source_impl.cc
@@ -35,6 +35,14 @@ namespace content { // static +WebUIDataSource* WebUIDataSource::CreateAndAdd(BrowserContext* browser_context, + const std::string& source_name) { + WebUIDataSource* data_source = WebUIDataSource::Create(source_name); + WebUIDataSource::Add(browser_context, data_source); + return data_source; +} + +// static WebUIDataSource* WebUIDataSource::Create(const std::string& source_name) { return new WebUIDataSourceImpl(source_name); }
diff --git a/content/browser/webui/web_ui_mojo_browsertest.cc b/content/browser/webui/web_ui_mojo_browsertest.cc index 43761e32..8f0b67f 100644 --- a/content/browser/webui/web_ui_mojo_browsertest.cc +++ b/content/browser/webui/web_ui_mojo_browsertest.cc
@@ -89,26 +89,24 @@ web_ui->SetBindings(bindings); { - WebUIDataSource* data_source = WebUIDataSource::Create(kMojoWebUiHost); + WebUIDataSource* data_source = WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), kMojoWebUiHost); data_source->OverrideContentSecurityPolicy( network::mojom::CSPDirectiveName::ScriptSrc, "script-src chrome://resources 'self' 'unsafe-eval';"); data_source->DisableTrustedTypesCSP(); data_source->AddResourcePaths(kMojoWebUiResources); data_source->AddResourcePath("", IDR_WEB_UI_MOJO_HTML); - WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), - data_source); } { - WebUIDataSource* data_source = WebUIDataSource::Create(kDummyWebUiHost); + WebUIDataSource* data_source = WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), kDummyWebUiHost); data_source->SetRequestFilter( base::BindRepeating([](const std::string& path) { return true; }), base::BindRepeating([](const std::string& id, WebUIDataSource::GotDataCallback callback) { std::move(callback).Run(new base::RefCountedString); })); - WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), - data_source); } }
diff --git a/content/browser/worker_host/mock_shared_worker.cc b/content/browser/worker_host/mock_shared_worker.cc index 4a80f8d4..7fa929b 100644 --- a/content/browser/worker_host/mock_shared_worker.cc +++ b/content/browser/worker_host/mock_shared_worker.cc
@@ -109,6 +109,7 @@ const blink::SharedWorkerToken& token, const url::Origin& constructor_origin, const std::string& user_agent, + const std::string& full_user_agent, const std::string& reduced_user_agent, const blink::UserAgentMetadata& ua_metadata, bool pause_on_start,
diff --git a/content/browser/worker_host/mock_shared_worker.h b/content/browser/worker_host/mock_shared_worker.h index 5830d8f1..11cab15 100644 --- a/content/browser/worker_host/mock_shared_worker.h +++ b/content/browser/worker_host/mock_shared_worker.h
@@ -89,6 +89,7 @@ const blink::SharedWorkerToken& token, const url::Origin& constructor_origin, const std::string& user_agent, + const std::string& full_user_agent, const std::string& reduced_user_agent, const blink::UserAgentMetadata& ua_metadata, bool pause_on_start,
diff --git a/content/browser/worker_host/shared_worker_host.cc b/content/browser/worker_host/shared_worker_host.cc index 0bcf573..e1e8b7b 100644 --- a/content/browser/worker_host/shared_worker_host.cc +++ b/content/browser/worker_host/shared_worker_host.cc
@@ -329,6 +329,7 @@ std::move(info), token_, instance_.storage_key().origin(), GetContentClient()->browser()->GetUserAgentBasedOnPolicy( GetProcessHost()->GetBrowserContext()), + GetContentClient()->browser()->GetFullUserAgent(), GetContentClient()->browser()->GetReducedUserAgent(), GetContentClient()->browser()->GetUserAgentMetadata(), devtools_handle_->pause_on_start(), devtools_handle_->dev_tools_token(),
diff --git a/content/common/renderer.mojom b/content/common/renderer.mojom index fd8c520..6181ea0811 100644 --- a/content/common/renderer.mojom +++ b/content/common/renderer.mojom
@@ -116,23 +116,6 @@ // Android. SetWebKitSharedTimersSuspended(bool suspend); - // Sets the user-agent string. This is needed because getting the value in the - // renderer from the system leads to a wrong value due to sandboxing. This - // must be called as early as possible, during the renderer process - // initialization. - SetUserAgent(string user_agent); - - // Sets a user-agent with high-entropy information reduced to common values. - // See `SetUserAgent` for caveats. - SetReducedUserAgent(string user_agent); - - // Sets the user agent metadata. This will replace `SetUserAgent()` if we - // decide to ship https://github.com/WICG/ua-client-hints. - SetUserAgentMetadata(blink.mojom.UserAgentMetadata metadata); - - // Sets the CORS exempt header list for sanity checking (e.g. DCHECKs). - SetCorsExemptHeaderList(array<string> list); - // Tells the renderer about a scrollbar appearance change. Only for use on // OS X. UpdateScrollbarTheme(UpdateScrollbarThemeParams params); @@ -186,4 +169,28 @@ // sites, because those features are highly privileged and shouldn't be // exposed to other sites. EnableBlinkRuntimeFeatures(array<string> features); + + // Initialize renderer user agent string, user agent metadata and CORS exempt + // header list on renderer startup. + // + // |user_agent| sets the user-agent string. This is needed because getting the + // value in the renderer from the system leads to a wrong value due to + // sandboxing. This must be called as early as possible, during the renderer + // process initialization. + // + // |full_user_agent| sets the full user-agent with high-entropy information. + // + // |reduced_user_agent| sets a user-agent with high-entropy information + // reduced to common values. + // + // |metadata| sets the user agent metadata. This will replace `SetUserAgent()` + // if we decide to ship https://github.com/WICG/ua-client-hints. + // + // |cors_exempt_header_list| sets the CORS exempt header list for sanity + // checking (e.g. DCHECKs). + InitializeRenderer(string user_agent, + string full_user_agent, + string reduced_user_agent, + blink.mojom.UserAgentMetadata metadata, + array<string> cors_exempt_header_list); };
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityNodeInfoUtils.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityNodeInfoUtils.java index e24db5f..a914ffcf 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityNodeInfoUtils.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/AccessibilityNodeInfoUtils.java
@@ -81,6 +81,10 @@ .append(node.getText().toString().replace("\n", "\\n")) .append("\""); } + // Print hint unless it is null or empty. + if (node.getHintText() != null && !node.getHintText().toString().isEmpty()) { + builder.append(" hint:\"").append(node.getHintText()).append("\""); + } // Text properties - Only print when non-null. if (node.getContentDescription() != null) { @@ -88,6 +92,9 @@ .append(node.getContentDescription().toString().replace("\n", "\\n")) .append("\""); } + if (node.getPaneTitle() != null) { + builder.append(" paneTitle:\"").append(node.getPaneTitle()).append("\""); + } if (node.getViewIdResourceName() != null) { builder.append(" viewIdResName:\"").append(node.getViewIdResourceName()).append("\""); }
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityState.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityState.java index 583bb95..61c47e1 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityState.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/BrowserAccessibilityState.java
@@ -171,6 +171,19 @@ } } + @VisibleForTesting + public static void setScreenReaderModeForTesting(boolean enabled) { + if (!sInitialized) updateAccessibilityServices(); + + // Explicitly set screen reader mode since a real screen reader isn't run during tests. + sScreenReader = enabled; + + // Inform all listeners of this change. + for (Listener listener : sListeners) { + listener.onBrowserAccessibilityStateChanged(sScreenReader); + } + } + static void updateAccessibilityServices() { sInitialized = true; sEventTypeMask = 0;
diff --git a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java index 7e46473..8ed237bf 100644 --- a/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java +++ b/content/public/android/java/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityImpl.java
@@ -169,11 +169,23 @@ public static final String PERCENTAGE_DROPPED_HISTOGRAM = "Accessibility.Android.OnDemand.PercentageDropped"; @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + public static final String PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_COMPLETE = + "Accessibility.Android.OnDemand.PercentageDropped.Complete"; + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + public static final String PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_BASIC = + "Accessibility.Android.OnDemand.PercentageDropped.Basic"; + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) public static final String EVENTS_DROPPED_HISTOGRAM = "Accessibility.Android.OnDemand.EventsDropped"; @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) public static final String ONE_HUNDRED_PERCENT_HISTOGRAM = "Accessibility.Android.OnDemand.OneHundredPercentEventsDropped"; + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + public static final String ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_COMPLETE = + "Accessibility.Android.OnDemand.OneHundredPercentEventsDropped.Complete"; + @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) + public static final String ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_BASIC = + "Accessibility.Android.OnDemand.OneHundredPercentEventsDropped.Basic"; private static final int EVENTS_DROPPED_HISTOGRAM_MIN_BUCKET = 1; private static final int EVENTS_DROPPED_HISTOGRAM_MAX_BUCKET = 10000; private static final int EVENTS_DROPPED_HISTOGRAM_BUCKET_COUNT = 100; @@ -486,6 +498,11 @@ BrowserAccessibilityState.setEventTypeMaskEmptyForTesting(); } + @VisibleForTesting + public void setScreenReaderModeForTesting(boolean enabled) { + BrowserAccessibilityState.setScreenReaderModeForTesting(enabled); + } + @CalledByNative public void handleEndOfTestSignal() { // We have received a signal that we have reached the end of a unit test. If we have a @@ -512,14 +529,28 @@ // Helper method to record UMA histograms for OnDemand feature and reset counters. private void recordUMAHistograms() { + // To investigate whether adding more AXModes could be beneficial, track separate + // stats when both the ComputeAXMode and OnDemand features are enabled. + boolean isComputeAXModeEnabled = + ContentFeatureList.isEnabled(ContentFeatureList.COMPUTE_AX_MODE); + // There are only 2 AXModes, kAXModeComplete is used when a screenreader is active. + boolean isAXModeComplete = BrowserAccessibilityState.screenReaderMode(); + // If we did not enqueue any events, we can ignore the data as a trivial case. if (mTotalEnqueuedEvents > 0) { // Log the percentage dropped (dispatching 0 events should be 100% dropped). int percentSent = (int) (mTotalDispatchedEvents * 1.0 / mTotalEnqueuedEvents * 100.0); RecordHistogram.recordPercentageHistogram( PERCENTAGE_DROPPED_HISTOGRAM, 100 - percentSent); + // Log the percentage dropped per AXMode as well. + if (isComputeAXModeEnabled) { + RecordHistogram.recordPercentageHistogram(isAXModeComplete + ? PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_COMPLETE + : PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_BASIC, + 100 - percentSent); + } - // Log the total number of dropped events. + // Log the total number of dropped events. (Not relevant to be tracked per AXMode) RecordHistogram.recordCustomCountHistogram(EVENTS_DROPPED_HISTOGRAM, mTotalEnqueuedEvents - mTotalDispatchedEvents, EVENTS_DROPPED_HISTOGRAM_MIN_BUCKET, EVENTS_DROPPED_HISTOGRAM_MAX_BUCKET, @@ -532,6 +563,17 @@ mTotalEnqueuedEvents - mTotalDispatchedEvents, EVENTS_DROPPED_HISTOGRAM_MIN_BUCKET, EVENTS_DROPPED_HISTOGRAM_MAX_BUCKET, EVENTS_DROPPED_HISTOGRAM_BUCKET_COUNT); + + // Log the 100% events count per AXMode as well. + if (isComputeAXModeEnabled) { + RecordHistogram.recordCustomCountHistogram(isAXModeComplete + ? ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_COMPLETE + : ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_BASIC, + mTotalEnqueuedEvents - mTotalDispatchedEvents, + EVENTS_DROPPED_HISTOGRAM_MIN_BUCKET, + EVENTS_DROPPED_HISTOGRAM_MAX_BUCKET, + EVENTS_DROPPED_HISTOGRAM_BUCKET_COUNT); + } } }
diff --git a/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java b/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java index 7538582a..965e4d41 100644 --- a/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java +++ b/content/public/android/java/src/org/chromium/content_public/browser/ContentFeatureList.java
@@ -35,6 +35,8 @@ public static final String BINDING_MANAGEMENT_WAIVE_CPU = "BindingManagementWaiveCpu"; + public static final String COMPUTE_AX_MODE = "ComputeAXMode"; + public static final String ON_DEMAND_ACCESSIBILITY_EVENTS = "OnDemandAccessibilityEvents"; public static final String PROCESS_SHARING_WITH_STRICT_SITE_INSTANCES =
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellActivityTestRule.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellActivityTestRule.java index 143f22e0..19b7b042 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellActivityTestRule.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/AccessibilityContentShellActivityTestRule.java
@@ -24,6 +24,7 @@ import org.junit.After; import org.junit.Assert; +import org.chromium.base.FeatureList; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; import org.chromium.base.test.util.UrlUtils; @@ -102,6 +103,8 @@ mTracker = new AccessibilityActionAndEventTracker(); mWcax.setAccessibilityTrackerForTesting(mTracker); + + FeatureList.setTestCanUseDefaultsForTesting(); } /** @@ -120,6 +123,9 @@ // Reset our test data. AccessibilityContentShellTestData.resetData(); + + FeatureList.resetTestCanUseDefaultsForTesting(); + FeatureList.setTestFeatures(null); } /**
diff --git a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java index 7cc5c6e3..ba38144 100644 --- a/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java +++ b/content/public/android/javatests/src/org/chromium/content/browser/accessibility/WebContentsAccessibilityTest.java
@@ -56,7 +56,11 @@ import static org.chromium.content.browser.accessibility.WebContentsAccessibilityImpl.EXTRA_DATA_TEXT_CHARACTER_LOCATION_ARG_START_INDEX; import static org.chromium.content.browser.accessibility.WebContentsAccessibilityImpl.EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY; import static org.chromium.content.browser.accessibility.WebContentsAccessibilityImpl.ONE_HUNDRED_PERCENT_HISTOGRAM; +import static org.chromium.content.browser.accessibility.WebContentsAccessibilityImpl.ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_BASIC; +import static org.chromium.content.browser.accessibility.WebContentsAccessibilityImpl.ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_COMPLETE; import static org.chromium.content.browser.accessibility.WebContentsAccessibilityImpl.PERCENTAGE_DROPPED_HISTOGRAM; +import static org.chromium.content.browser.accessibility.WebContentsAccessibilityImpl.PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_BASIC; +import static org.chromium.content.browser.accessibility.WebContentsAccessibilityImpl.PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_COMPLETE; import android.annotation.SuppressLint; import android.content.ClipData; @@ -81,6 +85,7 @@ import org.junit.Test; import org.junit.runner.RunWith; +import org.chromium.base.FeatureList; import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.test.util.Criteria; import org.chromium.base.test.util.CriteriaHelper; @@ -88,12 +93,15 @@ import org.chromium.base.test.util.MinAndroidSdkLevel; import org.chromium.base.test.util.Restriction; import org.chromium.base.test.util.UrlUtils; +import org.chromium.content_public.browser.ContentFeatureList; import org.chromium.content_public.browser.test.ContentJUnit4ClassRunner; import org.chromium.content_public.browser.test.util.TestThreadUtils; import org.chromium.ui.test.util.UiRestriction; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; +import java.util.Map; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; @@ -128,8 +136,8 @@ "Expected to receive both a traversal and selection text event"; private static final String BOUNDING_BOX_ERROR = "Expected bounding box to have updated values."; - private static final String ONDEMAND_HISTOGRAM_ERROR = - "Expected histogram for OnDemand AT feature to be recorded."; + private static final String UMA_HISTOGRAM_ERROR = + "Expected UMA histograms did not match recorded value."; private static final String VISIBLE_TO_USER_ERROR = "AccessibilityNodeInfo object has incorrect visibleToUser value"; private static final String OFFSCREEN_BUNDLE_EXTRA_ERROR = @@ -141,6 +149,15 @@ private static final String FOCUSING_ERROR = "Expected focus to be on a different node than it is."; + // ContentFeatureList maps used for various tests. + private static final Map<String, Boolean> ON_DEMAND_ON_COMPUTE_ON = + new HashMap<String, Boolean>() { + { + put(ContentFeatureList.ON_DEMAND_ACCESSIBILITY_EVENTS, true); + put(ContentFeatureList.COMPUTE_AX_MODE, true); + } + }; + // Constant values for unit tests private static final int UNSUPPRESSED_EXPECTED_COUNT = 15; @@ -362,90 +379,159 @@ } /** - * Test that UMA histograms are recorded for the OnDemand AT feature. + * Test that UMA histograms are recorded for the OnDemand AT feature and AX Mode complete. */ @Test @SmallTest - public void testOnDemandAccessibilityEventsUMARecorded() throws Throwable { + public void testUMAHistograms_OnDemand_AXModeComplete() throws Throwable { // Build a simple web page with a few nodes to traverse. setupTestWithHTML("<p>This is a test 1</p>\n" + "<p>This is a test 2</p>\n" + "<p>This is a test 3</p>"); - // Find the three text nodes. - int vvId1 = waitForNodeMatching(sTextMatcher, "This is a test 1"); - int vvId2 = waitForNodeMatching(sTextMatcher, "This is a test 2"); - int vvId3 = waitForNodeMatching(sTextMatcher, "This is a test 3"); - AccessibilityNodeInfoCompat mNodeInfo1 = createAccessibilityNodeInfo(vvId1); - AccessibilityNodeInfoCompat mNodeInfo2 = createAccessibilityNodeInfo(vvId2); - AccessibilityNodeInfoCompat mNodeInfo3 = createAccessibilityNodeInfo(vvId3); - Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo1); - Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo2); - Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo3); + // Set the relevant features and screen reader state. + FeatureList.setTestFeatures(ON_DEMAND_ON_COMPUTE_ON); + mActivityTestRule.mWcax.setScreenReaderModeForTesting(true); - // Focus each node in turn to generate events. - focusNode(vvId1); - focusNode(vvId2); - focusNode(vvId3); - - // Signal end of test. - mActivityTestRule.sendEndOfTestSignal(); - - // Force recording of UMA histograms. - mActivityTestRule.mWcax.forceRecordUMAHistogramsForTesting(); + performHistogramActions(); // Verify results were recorded in histograms. - Assert.assertEquals(ONDEMAND_HISTOGRAM_ERROR, 1, + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, RecordHistogram.getHistogramTotalCountForTesting(PERCENTAGE_DROPPED_HISTOGRAM)); - Assert.assertEquals(ONDEMAND_HISTOGRAM_ERROR, 1, + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting( + PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_COMPLETE)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, + RecordHistogram.getHistogramTotalCountForTesting( + PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_BASIC)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, RecordHistogram.getHistogramTotalCountForTesting(EVENTS_DROPPED_HISTOGRAM)); - Assert.assertEquals(ONDEMAND_HISTOGRAM_ERROR, 0, + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, RecordHistogram.getHistogramTotalCountForTesting(ONE_HUNDRED_PERCENT_HISTOGRAM)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, + RecordHistogram.getHistogramTotalCountForTesting( + ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_COMPLETE)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, + RecordHistogram.getHistogramTotalCountForTesting( + ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_BASIC)); } /** - * Test that UMA histogram for 100% events dropped is recorded for the OnDemand AT feature. + * Test that UMA histograms are recorded for the OnDemand AT feature and AX Mode basic. */ @Test @SmallTest - public void testOnDemandAccessibilityEventsUMARecorded_100Percent() throws Throwable { + public void testUMAHistograms_OnDemand_AXModeBasic() throws Throwable { // Build a simple web page with a few nodes to traverse. setupTestWithHTML("<p>This is a test 1</p>\n" + "<p>This is a test 2</p>\n" + "<p>This is a test 3</p>"); - // Set the relevant events type masks to be empty so no events are dispatched. - mActivityTestRule.mWcax.setEventTypeMaskEmptyForTesting(); + // Set the relevant features and screen reader state. + FeatureList.setTestFeatures(ON_DEMAND_ON_COMPUTE_ON); + mActivityTestRule.mWcax.setScreenReaderModeForTesting(false); - // Find the three text nodes. - int vvId1 = waitForNodeMatching(sTextMatcher, "This is a test 1"); - int vvId2 = waitForNodeMatching(sTextMatcher, "This is a test 2"); - int vvId3 = waitForNodeMatching(sTextMatcher, "This is a test 3"); - AccessibilityNodeInfoCompat mNodeInfo1 = createAccessibilityNodeInfo(vvId1); - AccessibilityNodeInfoCompat mNodeInfo2 = createAccessibilityNodeInfo(vvId2); - AccessibilityNodeInfoCompat mNodeInfo3 = createAccessibilityNodeInfo(vvId3); - Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo1); - Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo2); - Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo3); - - // Focus each node in turn to generate events. - focusNode(vvId1); - focusNode(vvId2); - focusNode(vvId3); - - // Signal end of test. - mActivityTestRule.sendEndOfTestSignal(); - - // Force recording of UMA histograms. - mActivityTestRule.mWcax.forceRecordUMAHistogramsForTesting(); + performHistogramActions(); // Verify results were recorded in histograms. - Assert.assertEquals(ONDEMAND_HISTOGRAM_ERROR, 1, + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, RecordHistogram.getHistogramTotalCountForTesting(PERCENTAGE_DROPPED_HISTOGRAM)); - Assert.assertEquals(ONDEMAND_HISTOGRAM_ERROR, 1, + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, + RecordHistogram.getHistogramTotalCountForTesting( + PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_COMPLETE)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting( + PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_BASIC)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, RecordHistogram.getHistogramTotalCountForTesting(EVENTS_DROPPED_HISTOGRAM)); - Assert.assertEquals(ONDEMAND_HISTOGRAM_ERROR, 1, + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, RecordHistogram.getHistogramTotalCountForTesting(ONE_HUNDRED_PERCENT_HISTOGRAM)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, + RecordHistogram.getHistogramTotalCountForTesting( + ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_COMPLETE)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, + RecordHistogram.getHistogramTotalCountForTesting( + ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_BASIC)); + } + + /** + * Test that UMA histograms are recorded for the OnDemand AT feature and AX Mode complete + * when 100% of events are dropped. + */ + @Test + @SmallTest + public void testUMAHistograms_OnDemand_AXModeComplete_100Percent() throws Throwable { + // Build a simple web page with a few nodes to traverse. + setupTestWithHTML("<p>This is a test 1</p>\n" + + "<p>This is a test 2</p>\n" + + "<p>This is a test 3</p>"); + + // Set the relevant features and screen reader state, set event type masks to empty. + FeatureList.setTestFeatures(ON_DEMAND_ON_COMPUTE_ON); + mActivityTestRule.mWcax.setEventTypeMaskEmptyForTesting(); + mActivityTestRule.mWcax.setScreenReaderModeForTesting(true); + + performHistogramActions(); + + // Verify results were recorded in histograms. + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting(PERCENTAGE_DROPPED_HISTOGRAM)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting( + PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_COMPLETE)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, + RecordHistogram.getHistogramTotalCountForTesting( + PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_BASIC)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting(EVENTS_DROPPED_HISTOGRAM)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting(ONE_HUNDRED_PERCENT_HISTOGRAM)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting( + ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_COMPLETE)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, + RecordHistogram.getHistogramTotalCountForTesting( + ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_BASIC)); + } + + /** + * Test that UMA histograms are recorded for the OnDemand AT feature and AX Mode basic + * when 100% of events are dropped. + */ + @Test + @SmallTest + public void testUMAHistograms_OnDemand_AXModeBasic_100Percent() throws Throwable { + // Build a simple web page with a few nodes to traverse. + setupTestWithHTML("<p>This is a test 1</p>\n" + + "<p>This is a test 2</p>\n" + + "<p>This is a test 3</p>"); + + // Set the relevant features and screen reader state, set event type masks to empty. + FeatureList.setTestFeatures(ON_DEMAND_ON_COMPUTE_ON); + mActivityTestRule.mWcax.setEventTypeMaskEmptyForTesting(); + mActivityTestRule.mWcax.setScreenReaderModeForTesting(false); + + performHistogramActions(); + + // Verify results were recorded in histograms. + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting(PERCENTAGE_DROPPED_HISTOGRAM)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, + RecordHistogram.getHistogramTotalCountForTesting( + PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_COMPLETE)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting( + PERCENTAGE_DROPPED_HISTOGRAM_AXMODE_BASIC)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting(EVENTS_DROPPED_HISTOGRAM)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting(ONE_HUNDRED_PERCENT_HISTOGRAM)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 0, + RecordHistogram.getHistogramTotalCountForTesting( + ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_COMPLETE)); + Assert.assertEquals(UMA_HISTOGRAM_ERROR, 1, + RecordHistogram.getHistogramTotalCountForTesting( + ONE_HUNDRED_PERCENT_HISTOGRAM_AXMODE_BASIC)); } /** @@ -2027,4 +2113,32 @@ return THRESHOLD_LOW_EVENT_COUNT_ERROR + " Received " + count + ", but expected at least: " + UNSUPPRESSED_EXPECTED_COUNT; } + + /** + * Helper method to perform a series of events that trigger histograms being tracked. + * @throws Throwable error on focusNode + */ + private void performHistogramActions() throws Throwable { + // Find the three text nodes. + int vvId1 = waitForNodeMatching(sTextMatcher, "This is a test 1"); + int vvId2 = waitForNodeMatching(sTextMatcher, "This is a test 2"); + int vvId3 = waitForNodeMatching(sTextMatcher, "This is a test 3"); + AccessibilityNodeInfoCompat mNodeInfo1 = createAccessibilityNodeInfo(vvId1); + AccessibilityNodeInfoCompat mNodeInfo2 = createAccessibilityNodeInfo(vvId2); + AccessibilityNodeInfoCompat mNodeInfo3 = createAccessibilityNodeInfo(vvId3); + Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo1); + Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo2); + Assert.assertNotNull(NODE_TIMEOUT_ERROR, mNodeInfo3); + + // Focus each node in turn to generate events. + focusNode(vvId1); + focusNode(vvId2); + focusNode(vvId3); + + // Signal end of test. + mActivityTestRule.sendEndOfTestSignal(); + + // Force recording of UMA histograms. + mActivityTestRule.mWcax.forceRecordUMAHistogramsForTesting(); + } }
diff --git a/content/public/browser/BUILD.gn b/content/public/browser/BUILD.gn index 1d788a7..b23debc 100644 --- a/content/public/browser/BUILD.gn +++ b/content/public/browser/BUILD.gn
@@ -28,6 +28,7 @@ sources = [ "allow_service_worker_result.cc", "allow_service_worker_result.h", + "attribution_reporting.h", "audio_service.h", "audio_service_info.cc", "audio_service_info.h",
diff --git a/content/public/browser/attribution_reporting.h b/content/public/browser/attribution_reporting.h new file mode 100644 index 0000000..8d08da37 --- /dev/null +++ b/content/public/browser/attribution_reporting.h
@@ -0,0 +1,30 @@ +// Copyright 2022 The Chromium 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_BROWSER_ATTRIBUTION_REPORTING_H_ +#define CONTENT_PUBLIC_BROWSER_ATTRIBUTION_REPORTING_H_ + +namespace content { + +enum class AttributionNoiseMode { + // Various aspects of the API are subject to noise: + // - Sources are subject to randomized response + // - Reports within a reporting window are shuffled + // - Pending reports are randomly delayed when the browser comes online + kDefault, + // None of the above applies. + kNone, +}; + +enum class AttributionDelayMode { + // Reports are sent in reporting windows some time after attribution is + // triggered. + kDefault, + // Reports are sent immediately after attribution is triggered. + kNone, +}; + +} // namespace content + +#endif // CONTENT_PUBLIC_BROWSER_ATTRIBUTION_REPORTING_H_
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc index e4be60c..eec8522 100644 --- a/content/public/browser/content_browser_client.cc +++ b/content/public/browser/content_browser_client.cc
@@ -1066,6 +1066,10 @@ return GetUserAgent(); } +std::string ContentBrowserClient::GetFullUserAgent() { + return GetUserAgent(); +} + std::string ContentBrowserClient::GetReducedUserAgent() { return GetUserAgent(); }
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h index db75a34..585024d 100644 --- a/content/public/browser/content_browser_client.h +++ b/content/public/browser/content_browser_client.h
@@ -1888,6 +1888,10 @@ virtual std::string GetUserAgentBasedOnPolicy( content::BrowserContext* context); + // Returns the full user agent string. Defaults to |GetUserAgent|. Content + // may cache this value. + virtual std::string GetFullUserAgent(); + // Returns the reduced user agent string. Defaults to |GetUserAgent|. Content // may cache this value. virtual std::string GetReducedUserAgent();
diff --git a/content/public/browser/web_contents_view_delegate.cc b/content/public/browser/web_contents_view_delegate.cc index da88d532..836548a 100644 --- a/content/public/browser/web_contents_view_delegate.cc +++ b/content/public/browser/web_contents_view_delegate.cc
@@ -28,6 +28,8 @@ RenderFrameHost& render_frame_host, const ContextMenuParams& params) {} +void WebContentsViewDelegate::DismissContextMenu() {} + void WebContentsViewDelegate::ExecuteCommandForTesting(int command_id, int event_flags) { NOTREACHED();
diff --git a/content/public/browser/web_contents_view_delegate.h b/content/public/browser/web_contents_view_delegate.h index 36a5749e..0dd68b21 100644 --- a/content/public/browser/web_contents_view_delegate.h +++ b/content/public/browser/web_contents_view_delegate.h
@@ -58,6 +58,9 @@ virtual void ShowContextMenu(RenderFrameHost& render_frame_host, const ContextMenuParams& params); + // Dismiss the context menu if one exists. + virtual void DismissContextMenu(); + // Tests can use ExecuteCommandForTesting to simulate executing a context menu // item (after first opening the context menu using the ShowContextMenu // method).
diff --git a/content/public/browser/web_ui_data_source.h b/content/public/browser/web_ui_data_source.h index 7ce0943..486dc6a1 100644 --- a/content/public/browser/web_ui_data_source.h +++ b/content/public/browser/web_ui_data_source.h
@@ -38,6 +38,15 @@ public: virtual ~WebUIDataSource() {} + // Calls `Create()` and `Add()` to internalize ownership of the + // WebUIDataSource instance. Callers just get a raw pointer, which they don't + // own. Prefer `CreateAndAdd` in new code. + CONTENT_EXPORT static WebUIDataSource* CreateAndAdd( + BrowserContext* browser_context, + const std::string& source_name); + + // Creates a WebUIDataSource instance. Caller takes ownership of returned + // pointer. Prefer `CreateAndAdd()` when possible. CONTENT_EXPORT static WebUIDataSource* Create(const std::string& source_name); // Adds a WebUI data source to |browser_context|. TODO(dbeam): update this API
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc index 9e36b3b..bcd49295 100644 --- a/content/public/common/content_features.cc +++ b/content/public/common/content_features.cc
@@ -1199,6 +1199,14 @@ const char kBigLittleSchedulingGpuMainBigParam[] = "BigLittleSchedulingGpuMainBigParam"; +// When the context menu is triggered, the browser allows motion in a small +// region around the initial touch location menu to allow for finger jittering. +// This param holds the movement threshold in DIPs to consider drag an +// intentional drag, which will dismiss the current context menu and prevent new +// menu from showing. +const char kDragAndDropMovementThresholdDipParam[] = + "DragAndDropMovementThresholdDipParam"; + // Temporarily pauses the compositor early in navigation. const base::Feature kOptimizeEarlyNavigation{"OptimizeEarlyNavigation", base::FEATURE_DISABLED_BY_DEFAULT};
diff --git a/content/public/common/content_features.h b/content/public/common/content_features.h index c4de8429..6cad440 100644 --- a/content/public/common/content_features.h +++ b/content/public/common/content_features.h
@@ -303,6 +303,7 @@ extern const char kBigLittleSchedulingRenderMainBigParam[]; extern const char kBigLittleSchedulingNetworkMainBigParam[]; extern const char kBigLittleSchedulingGpuMainBigParam[]; +extern const char kDragAndDropMovementThresholdDipParam[]; CONTENT_EXPORT extern const base::Feature kOptimizeEarlyNavigation; CONTENT_EXPORT extern const base::FeatureParam<base::TimeDelta>
diff --git a/content/public/renderer/content_renderer_client.cc b/content/public/renderer/content_renderer_client.cc index 46efb19..fac0b275 100644 --- a/content/public/renderer/content_renderer_client.cc +++ b/content/public/renderer/content_renderer_client.cc
@@ -156,8 +156,10 @@ return true; } -void ContentRendererClient::AddSupportedKeySystems( - std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) {} +void ContentRendererClient::GetSupportedKeySystems( + media::GetSupportedKeySystemsCB cb) { + std::move(cb).Run({}); +} bool ContentRendererClient::IsKeySystemsUpdateNeeded() { return false;
diff --git a/content/public/renderer/content_renderer_client.h b/content/public/renderer/content_renderer_client.h index 3c5b962a..63ead7f8 100644 --- a/content/public/renderer/content_renderer_client.h +++ b/content/public/renderer/content_renderer_client.h
@@ -21,6 +21,7 @@ #include "content/public/common/alternative_error_page_override_info.mojom.h" #include "content/public/common/content_client.h" #include "media/base/audio_parameters.h" +#include "media/base/key_system_properties.h" #include "media/base/supported_types.h" #include "third_party/abseil-cpp/absl/types/optional.h" #include "third_party/blink/public/platform/url_loader_throttle_provider.h" @@ -63,7 +64,6 @@ class DecoderFactory; class Demuxer; class GpuVideoAcceleratorFactories; -class KeySystemProperties; class MediaLog; class RendererFactory; } @@ -251,14 +251,12 @@ // language. virtual bool IsOriginIsolatedPepperPlugin(const base::FilePath& plugin_path); - // Allows embedder to register the key system(s) it supports by populating - // |key_systems|. - virtual void AddSupportedKeySystems( - std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems); + // Allows embedder to register the key system(s) it supports. + virtual void GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb); // Signal that embedder has changed key systems. // TODO(chcunningham): Refactor this to a proper change "observer" API that is - // less fragile (don't assume AddSupportedKeySystems has just one caller). + // less fragile (don't assume GetSupportedKeySystems has just one caller). virtual bool IsKeySystemsUpdateNeeded(); // Allows embedder to describe customized audio capabilities.
diff --git a/content/public/renderer/key_system_support.cc b/content/public/renderer/key_system_support.cc index ed71bfa..7ffed2be 100644 --- a/content/public/renderer/key_system_support.cc +++ b/content/public/renderer/key_system_support.cc
@@ -11,19 +11,31 @@ namespace content { -bool IsKeySystemSupported( - const std::string& key_system, - media::mojom::KeySystemCapabilityPtr* key_system_capability) { - DVLOG(3) << __func__ << " key_system: " << key_system; +namespace { - bool is_supported = false; +// Helper function to help hold the `key_system_support` remote. +void OnIsKeySystemSupportedResult( + mojo::Remote<media::mojom::KeySystemSupport> key_system_support, + IsKeySystemSupportedCB cb, + bool is_supported, + media::mojom::KeySystemCapabilityPtr capability) { + std::move(cb).Run(is_supported, std::move(capability)); +} + +} // namespace + +void IsKeySystemSupported(const std::string& key_system, + IsKeySystemSupportedCB cb) { + DVLOG(3) << __func__ << ": key_system=" << key_system; + mojo::Remote<media::mojom::KeySystemSupport> key_system_support; content::RenderThread::Get()->BindHostReceiver( key_system_support.BindNewPipeAndPassReceiver()); - key_system_support->IsKeySystemSupported(key_system, &is_supported, - key_system_capability); - return is_supported; + auto* key_system_support_raw = key_system_support.get(); + key_system_support_raw->IsKeySystemSupported( + key_system, base::BindOnce(&OnIsKeySystemSupportedResult, + std::move(key_system_support), std::move(cb))); } } // namespace content
diff --git a/content/public/renderer/key_system_support.h b/content/public/renderer/key_system_support.h index bc367e8..911799c 100644 --- a/content/public/renderer/key_system_support.h +++ b/content/public/renderer/key_system_support.h
@@ -13,12 +13,13 @@ namespace content { -// Determines if |key_system| is supported by calling into the browser. -// If it is supported, return true and |key_system_capability| is updated -// to match what |key_system| supports. If not supported, false is returned. -CONTENT_EXPORT bool IsKeySystemSupported( - const std::string& key_system, - media::mojom::KeySystemCapabilityPtr* key_system_capability); +using IsKeySystemSupportedCB = + media::mojom::KeySystemSupport::IsKeySystemSupportedCallback; + +// Determines if |key_system| is supported by calling into the browser and +// calls the `cb` with the result. +CONTENT_EXPORT void IsKeySystemSupported(const std::string& key_system, + IsKeySystemSupportedCB cb); } // namespace content
diff --git a/content/public/renderer/render_thread.h b/content/public/renderer/render_thread.h index 463df946..f5e7207 100644 --- a/content/public/renderer/render_thread.h +++ b/content/public/renderer/render_thread.h
@@ -112,6 +112,7 @@ // Returns the user-agent string. virtual blink::WebString GetUserAgent() = 0; + virtual blink::WebString GetFullUserAgent() = 0; virtual blink::WebString GetReducedUserAgent() = 0; virtual const blink::UserAgentMetadata& GetUserAgentMetadata() = 0;
diff --git a/content/public/test/attribution_simulator.h b/content/public/test/attribution_simulator.h index f0e6aac..d7654023 100644 --- a/content/public/test/attribution_simulator.h +++ b/content/public/test/attribution_simulator.h
@@ -5,6 +5,8 @@ #ifndef CONTENT_PUBLIC_TEST_ATTRIBUTION_SIMULATOR_H_ #define CONTENT_PUBLIC_TEST_ATTRIBUTION_SIMULATOR_H_ +#include "content/public/browser/attribution_reporting.h" + namespace base { class Value; } // namespace base @@ -12,6 +14,10 @@ namespace content { struct AttributionSimulationOptions { + AttributionNoiseMode noise_mode = AttributionNoiseMode::kDefault; + + AttributionDelayMode delay_mode = AttributionDelayMode::kDefault; + // If true, removes the `report_id` field from reports before output. // // This field normally contains a random GUID used by the reporting origin
diff --git a/content/public/test/mock_render_thread.cc b/content/public/test/mock_render_thread.cc index 9f812f9..384e7bd 100644 --- a/content/public/test/mock_render_thread.cc +++ b/content/public/test/mock_render_thread.cc
@@ -217,6 +217,10 @@ return blink::WebString(); } +blink::WebString MockRenderThread::GetFullUserAgent() { + return blink::WebString(); +} + blink::WebString MockRenderThread::GetReducedUserAgent() { return blink::WebString(); }
diff --git a/content/public/test/mock_render_thread.h b/content/public/test/mock_render_thread.h index 0fa80cf..455daa74f 100644 --- a/content/public/test/mock_render_thread.h +++ b/content/public/test/mock_render_thread.h
@@ -82,6 +82,7 @@ void SetRendererProcessType( blink::scheduler::WebRendererProcessType type) override; blink::WebString GetUserAgent() override; + blink::WebString GetFullUserAgent() override; blink::WebString GetReducedUserAgent() override; const blink::UserAgentMetadata& GetUserAgentMetadata() override; bool IsUseZoomForDSF() override;
diff --git a/content/public/test/web_ui_browsertest_util.cc b/content/public/test/web_ui_browsertest_util.cc index dfa0130..b3afa11 100644 --- a/content/public/test/web_ui_browsertest_util.cc +++ b/content/public/test/web_ui_browsertest_util.cc
@@ -74,7 +74,8 @@ web_ui_impl->AddRequestableScheme(scheme.c_str()); } - WebUIDataSource* data_source = WebUIDataSource::Create(base_url.host()); + WebUIDataSource* data_source = WebUIDataSource::CreateAndAdd( + web_ui->GetWebContents()->GetBrowserContext(), base_url.host()); data_source->SetRequestFilter( base::BindRepeating([](const std::string& path) { return true; }), base::BindRepeating(&GetResource)); @@ -90,9 +91,6 @@ data_source->DisableDenyXFrameOptions(); if (config.disable_trusted_types) data_source->DisableTrustedTypesCSP(); - - WebUIDataSource::Add(web_ui->GetWebContents()->GetBrowserContext(), - data_source); } TestWebUIController(const TestWebUIController&) = delete; void operator=(const TestWebUIController&) = delete; @@ -109,8 +107,8 @@ BrowserContext* browser_context, const std::string& host, absl::optional<TestUntrustedDataSourceHeaders> headers) { - auto* untrusted_data_source = - WebUIDataSource::Create(GetChromeUntrustedUIURL(host).spec()); + auto* untrusted_data_source = WebUIDataSource::CreateAndAdd( + browser_context, GetChromeUntrustedUIURL(host).spec()); untrusted_data_source->SetRequestFilter( base::BindRepeating([](const std::string& path) { return true; }), base::BindRepeating(&GetResource)); @@ -160,8 +158,6 @@ } } } - - WebUIDataSource::Add(browser_context, untrusted_data_source); } // static
diff --git a/content/renderer/java/gin_java_bridge_dispatcher.cc b/content/renderer/java/gin_java_bridge_dispatcher.cc index db8ef72..353ebb8 100644 --- a/content/renderer/java/gin_java_bridge_dispatcher.cc +++ b/content/renderer/java/gin_java_bridge_dispatcher.cc
@@ -105,10 +105,10 @@ arguments, &result_wrapper, error)); - base::Value* result; - if (!result_wrapper.Get(0, &result)) + const auto& list = result_wrapper.GetListDeprecated(); + if (list.empty()) return nullptr; - return base::Value::ToUniquePtrValue(result->Clone()); + return base::Value::ToUniquePtrValue(list[0].Clone()); } GinJavaBridgeObject* GinJavaBridgeDispatcher::GetObject(ObjectID object_id) {
diff --git a/content/renderer/media/render_media_client.cc b/content/renderer/media/render_media_client.cc index e4f7291..9d8112c 100644 --- a/content/renderer/media/render_media_client.cc +++ b/content/renderer/media/render_media_client.cc
@@ -25,9 +25,9 @@ RenderMediaClient::~RenderMediaClient() { } -void RenderMediaClient::AddSupportedKeySystems( - std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) { - GetContentClient()->renderer()->AddSupportedKeySystems(key_systems); +void RenderMediaClient::GetSupportedKeySystems( + media::GetSupportedKeySystemsCB cb) { + GetContentClient()->renderer()->GetSupportedKeySystems(std::move(cb)); } bool RenderMediaClient::IsKeySystemsUpdateNeeded() {
diff --git a/content/renderer/media/render_media_client.h b/content/renderer/media/render_media_client.h index 8b18159..6997146 100644 --- a/content/renderer/media/render_media_client.h +++ b/content/renderer/media/render_media_client.h
@@ -22,9 +22,7 @@ static void Initialize(); // MediaClient implementation. - void AddSupportedKeySystems( - std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) - final; + void GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb) final; bool IsKeySystemsUpdateNeeded() final; bool IsSupportedAudioType(const media::AudioType& type) final; bool IsSupportedVideoType(const media::VideoType& type) final;
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc index f6574e1..0b42cba 100644 --- a/content/renderer/render_thread_impl.cc +++ b/content/renderer/render_thread_impl.cc
@@ -968,6 +968,24 @@ blink::WebImageGenerator::CreateAsSkImageGenerator); } +void RenderThreadImpl::InitializeRenderer( + const std::string& user_agent, + const std::string& full_user_agent, + const std::string& reduced_user_agent, + const blink::UserAgentMetadata& user_agent_metadata, + const std::vector<std::string>& cors_exempt_header_list) { + DCHECK(user_agent_.IsNull()); + DCHECK(reduced_user_agent_.IsNull()); + DCHECK(full_user_agent_.IsNull()); + + user_agent_ = WebString::FromUTF8(user_agent); + GetContentClient()->renderer()->DidSetUserAgent(user_agent); + full_user_agent_ = WebString::FromUTF8(full_user_agent); + reduced_user_agent_ = WebString::FromUTF8(reduced_user_agent); + user_agent_metadata_ = user_agent_metadata; + cors_exempt_header_list_ = cors_exempt_header_list; +} + void RenderThreadImpl::RegisterSchemes() { // chrome: WebString chrome_scheme(WebString::FromASCII(kChromeUIScheme)); @@ -1288,6 +1306,12 @@ return user_agent_; } +blink::WebString RenderThreadImpl::GetFullUserAgent() { + DCHECK(!full_user_agent_.IsNull()); + + return full_user_agent_; +} + blink::WebString RenderThreadImpl::GetReducedUserAgent() { DCHECK(!reduced_user_agent_.IsNull()); @@ -1700,27 +1724,6 @@ #endif } -void RenderThreadImpl::SetUserAgent(const std::string& user_agent) { - DCHECK(user_agent_.IsNull()); - user_agent_ = WebString::FromUTF8(user_agent); - GetContentClient()->renderer()->DidSetUserAgent(user_agent); -} - -void RenderThreadImpl::SetReducedUserAgent(const std::string& user_agent) { - DCHECK(reduced_user_agent_.IsNull()); - reduced_user_agent_ = WebString::FromUTF8(user_agent); -} - -void RenderThreadImpl::SetUserAgentMetadata( - const blink::UserAgentMetadata& user_agent_metadata) { - user_agent_metadata_ = user_agent_metadata; -} - -void RenderThreadImpl::SetCorsExemptHeaderList( - const std::vector<std::string>& list) { - cors_exempt_header_list_ = list; -} - void RenderThreadImpl::UpdateScrollbarTheme( mojom::UpdateScrollbarThemeParamsPtr params) { #if BUILDFLAG(IS_MAC) @@ -1802,15 +1805,14 @@ void RenderThreadImpl::OnMemoryPressure( base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level) { - TRACE_EVENT("memory", "RenderThreadImpl::OnMemoryPressure", - [&](perfetto::EventContext ctx) { - auto* event = - ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>(); - auto* data = event->set_chrome_memory_pressure_notification(); - data->set_level( - base::trace_event::MemoryPressureLevelToTraceEnum( - memory_pressure_level)); - }); + TRACE_EVENT( + "memory", "RenderThreadImpl::OnMemoryPressure", + [&](perfetto::EventContext ctx) { + auto* event = ctx.event<perfetto::protos::pbzero::ChromeTrackEvent>(); + auto* data = event->set_chrome_memory_pressure_notification(); + data->set_level(base::trace_event::MemoryPressureLevelToTraceEnum( + memory_pressure_level)); + }); if (blink_platform_impl_) blink::WebMemoryPressureListener::OnMemoryPressure(memory_pressure_level); if (memory_pressure_level ==
diff --git a/content/renderer/render_thread_impl.h b/content/renderer/render_thread_impl.h index b2e886d..238ef650 100644 --- a/content/renderer/render_thread_impl.h +++ b/content/renderer/render_thread_impl.h
@@ -188,6 +188,7 @@ void SetRendererProcessType( blink::scheduler::WebRendererProcessType type) override; blink::WebString GetUserAgent() override; + blink::WebString GetFullUserAgent() override; blink::WebString GetReducedUserAgent() override; const blink::UserAgentMetadata& GetUserAgentMetadata() override; bool IsUseZoomForDSF() override; @@ -446,10 +447,12 @@ base::TimeDelta transport_rtt, double bandwidth_kbps) override; void SetWebKitSharedTimersSuspended(bool suspend) override; - void SetUserAgent(const std::string& user_agent) override; - void SetReducedUserAgent(const std::string& user_agent) override; - void SetUserAgentMetadata(const blink::UserAgentMetadata& metadata) override; - void SetCorsExemptHeaderList(const std::vector<std::string>& list) override; + void InitializeRenderer( + const std::string& user_agent, + const std::string& full_user_agent, + const std::string& reduced_user_agent, + const blink::UserAgentMetadata& user_agent_metadata, + const std::vector<std::string>& cors_exempt_header_list) override; void UpdateScrollbarTheme( mojom::UpdateScrollbarThemeParamsPtr params) override; void OnSystemColorsChanged(int32_t aqua_color_variant, @@ -515,6 +518,7 @@ absl::optional<mojom::RenderProcessVisibleState> visible_state_; blink::WebString user_agent_; + blink::WebString full_user_agent_; blink::WebString reduced_user_agent_; blink::UserAgentMetadata user_agent_metadata_;
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc index b4e37bb..a64d78c 100644 --- a/content/renderer/renderer_blink_platform_impl.cc +++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -313,6 +313,14 @@ return render_thread->GetUserAgent(); } +blink::WebString RendererBlinkPlatformImpl::FullUserAgent() { + auto* render_thread = RenderThreadImpl::current(); + // RenderThreadImpl is null in some tests. + if (!render_thread) + return WebString(); + return render_thread->GetFullUserAgent(); +} + blink::WebString RendererBlinkPlatformImpl::ReducedUserAgent() { auto* render_thread = RenderThreadImpl::current(); // RenderThreadImpl is null in some tests.
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h index 2191ab72..10c96d3 100644 --- a/content/renderer/renderer_blink_platform_impl.h +++ b/content/renderer/renderer_blink_platform_impl.h
@@ -86,6 +86,7 @@ uint64_t VisitedLinkHash(const char* canonicalURL, size_t length) override; bool IsLinkVisited(uint64_t linkHash) override; blink::WebString UserAgent() override; + blink::WebString FullUserAgent() override; blink::WebString ReducedUserAgent() override; blink::UserAgentMetadata UserAgentMetadata() override; void CacheMetadata(blink::mojom::CodeCacheType cache_type,
diff --git a/content/renderer/v8_value_converter_impl_unittest.cc b/content/renderer/v8_value_converter_impl_unittest.cc index eef8372..a662f8c 100644 --- a/content/renderer/v8_value_converter_impl_unittest.cc +++ b/content/renderer/v8_value_converter_impl_unittest.cc
@@ -176,12 +176,12 @@ } bool IsNull(base::ListValue* value, uint32_t index) { - base::Value* child = nullptr; - if (!value->Get(static_cast<size_t>(index), &child)) { + const auto& list = value->GetListDeprecated(); + if (list.size() <= index) { ADD_FAILURE(); return false; } - return child->type() == base::Value::Type::NONE; + return list[index].type() == base::Value::Type::NONE; } bool IsNull(v8::Local<v8::Array> value, uint32_t index) {
diff --git a/content/renderer/worker/embedded_shared_worker_stub.cc b/content/renderer/worker/embedded_shared_worker_stub.cc index 5e851e7..49c44cc2 100644 --- a/content/renderer/worker/embedded_shared_worker_stub.cc +++ b/content/renderer/worker/embedded_shared_worker_stub.cc
@@ -36,6 +36,7 @@ const blink::SharedWorkerToken& token, const url::Origin& constructor_origin, const std::string& user_agent, + const std::string& full_user_agent, const std::string& reduced_user_agent, const blink::UserAgentMetadata& ua_metadata, bool pause_on_start, @@ -118,6 +119,7 @@ blink::WebString::FromUTF8(info->options->name), blink::WebSecurityOrigin(constructor_origin), blink::WebString::FromUTF8(user_agent), + blink::WebString::FromUTF8(full_user_agent), blink::WebString::FromUTF8(reduced_user_agent), ua_metadata, ToWebContentSecurityPolicies(std::move(info->content_security_policies)), info->creation_address_space,
diff --git a/content/renderer/worker/embedded_shared_worker_stub.h b/content/renderer/worker/embedded_shared_worker_stub.h index 3a10b6a..aeb3b6fe 100644 --- a/content/renderer/worker/embedded_shared_worker_stub.h +++ b/content/renderer/worker/embedded_shared_worker_stub.h
@@ -59,6 +59,7 @@ const blink::SharedWorkerToken& token, const url::Origin& constructor_origin, const std::string& user_agent, + const std::string& full_user_agent, const std::string& reduced_user_agent, const blink::UserAgentMetadata& ua_metadata, bool pause_on_start,
diff --git a/content/renderer/worker/shared_worker_factory_impl.cc b/content/renderer/worker/shared_worker_factory_impl.cc index ec7a525..e4e834f7 100644 --- a/content/renderer/worker/shared_worker_factory_impl.cc +++ b/content/renderer/worker/shared_worker_factory_impl.cc
@@ -27,6 +27,7 @@ const blink::SharedWorkerToken& token, const url::Origin& constructor_origin, const std::string& user_agent, + const std::string& full_user_agent, const std::string& reduced_user_agent, const blink::UserAgentMetadata& ua_metadata, bool pause_on_start, @@ -49,7 +50,7 @@ ukm::SourceId ukm_source_id) { // Bound to the lifetime of the underlying blink::WebSharedWorker instance. new EmbeddedSharedWorkerStub( - std::move(info), token, constructor_origin, user_agent, + std::move(info), token, constructor_origin, user_agent, full_user_agent, reduced_user_agent, ua_metadata, pause_on_start, devtools_worker_token, renderer_preferences, std::move(preference_watcher_receiver), std::move(content_settings), std::move(service_worker_container_info),
diff --git a/content/renderer/worker/shared_worker_factory_impl.h b/content/renderer/worker/shared_worker_factory_impl.h index e8101f0..60b82f3a 100644 --- a/content/renderer/worker/shared_worker_factory_impl.h +++ b/content/renderer/worker/shared_worker_factory_impl.h
@@ -35,6 +35,7 @@ const blink::SharedWorkerToken& token, const url::Origin& constructor_origin, const std::string& user_agent, + const std::string& full_user_agent, const std::string& reduced_user_agent, const blink::UserAgentMetadata& ua_metadata, bool pause_on_start,
diff --git a/content/shell/browser/shell_content_browser_client.cc b/content/shell/browser/shell_content_browser_client.cc index 2d6de5b..56605576 100644 --- a/content/shell/browser/shell_content_browser_client.cc +++ b/content/shell/browser/shell_content_browser_client.cc
@@ -170,6 +170,15 @@ bool IsEnterprise() override { return false; } }; +// Returns the full user agent string for the content shell. +std::string GetShellFullUserAgent() { + std::string product = "Chrome/" CONTENT_SHELL_VERSION; + base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); + if (command_line->HasSwitch(switches::kUseMobileUserAgent)) + product += " Mobile"; + return BuildUserAgentFromProduct(product); +} + // Returns the reduced user agent string for the content shell. std::string GetShellReducedUserAgent() { base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); @@ -195,14 +204,13 @@ }; std::string GetShellUserAgent() { + if (base::FeatureList::IsEnabled(blink::features::kFullUserAgent)) + return GetShellFullUserAgent(); + if (base::FeatureList::IsEnabled(blink::features::kReduceUserAgent)) return GetShellReducedUserAgent(); - std::string product = "Chrome/" CONTENT_SHELL_VERSION; - base::CommandLine* command_line = base::CommandLine::ForCurrentProcess(); - if (command_line->HasSwitch(switches::kUseMobileUserAgent)) - product += " Mobile"; - return BuildUserAgentFromProduct(product); + return GetShellFullUserAgent(); } std::string GetShellLanguage() { @@ -481,6 +489,10 @@ return GetShellUserAgent(); } +std::string ShellContentBrowserClient::GetFullUserAgent() { + return GetShellFullUserAgent(); +} + std::string ShellContentBrowserClient::GetReducedUserAgent() { return GetShellReducedUserAgent(); }
diff --git a/content/shell/browser/shell_content_browser_client.h b/content/shell/browser/shell_content_browser_client.h index 6e61db23..406f4647 100644 --- a/content/shell/browser/shell_content_browser_client.h +++ b/content/shell/browser/shell_content_browser_client.h
@@ -97,6 +97,7 @@ base::DictionaryValue GetNetLogConstants() override; base::FilePath GetSandboxedStorageServiceDataDirectory() override; std::string GetUserAgent() override; + std::string GetFullUserAgent() override; std::string GetReducedUserAgent() override; blink::UserAgentMetadata GetUserAgentMetadata() override; void OverrideURLLoaderFactoryParams(
diff --git a/content/shell/renderer/shell_content_renderer_client.cc b/content/shell/renderer/shell_content_renderer_client.cc index 8ae4719..0194e1ca 100644 --- a/content/shell/renderer/shell_content_renderer_client.cc +++ b/content/shell/renderer/shell_content_renderer_client.cc
@@ -192,12 +192,12 @@ } #if BUILDFLAG(ENABLE_MOJO_CDM) -void ShellContentRendererClient::AddSupportedKeySystems( - std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) { - if (!base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting)) - return; - - key_systems->push_back(std::make_unique<cdm::ExternalClearKeyProperties>()); +void ShellContentRendererClient::GetSupportedKeySystems( + media::GetSupportedKeySystemsCB cb) { + media::KeySystemPropertiesVector key_systems; + if (base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting)) + key_systems.push_back(std::make_unique<cdm::ExternalClearKeyProperties>()); + std::move(cb).Run(std::move(key_systems)); } #endif
diff --git a/content/shell/renderer/shell_content_renderer_client.h b/content/shell/renderer/shell_content_renderer_client.h index b6d196d..617af07 100644 --- a/content/shell/renderer/shell_content_renderer_client.h +++ b/content/shell/renderer/shell_content_renderer_client.h
@@ -47,9 +47,7 @@ v8::Local<v8::Context> context) override; #if BUILDFLAG(ENABLE_MOJO_CDM) - void AddSupportedKeySystems( - std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) - override; + void GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb) override; #endif private:
diff --git a/content/test/attribution_simulator_impl.cc b/content/test/attribution_simulator_impl.cc index 7eda597..a6d5dd7 100644 --- a/content/test/attribution_simulator_impl.cc +++ b/content/test/attribution_simulator_impl.cc
@@ -13,7 +13,6 @@ #include "base/run_loop.h" #include "base/test/bind.h" #include "base/test/task_environment.h" -#include "base/test/test_timeouts.h" #include "base/values.h" #include "content/browser/attribution_reporting/attribution_manager_impl.h" #include "content/browser/attribution_reporting/attribution_storage_delegate_impl.h" @@ -125,7 +124,6 @@ const base::Value& input, const AttributionSimulationOptions& options) { // Prerequisites for using an environment with mock time. - TestTimeouts::Initialize(); content::BrowserTaskEnvironment task_environment( base::test::TaskEnvironment::TimeSource::MOCK_TIME); @@ -152,7 +150,8 @@ auto manager = AttributionManagerImpl::CreateForTesting( std::move(always_allow_reports_callback), user_data_directory, /*special_storage_policy=*/nullptr, - std::make_unique<AttributionStorageDelegateImpl>(), + std::make_unique<AttributionStorageDelegateImpl>(options.noise_mode, + options.delay_mode), std::make_unique<AlwaysSetCookieChecker>(), /*network_sender=*/ std::make_unique<SentReportAccumulator>(reports,
diff --git a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt index 755b0f4e..0dc7bb2d 100644 --- a/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt +++ b/content/test/data/accessibility/accname/desc-from-content-of-describedby-element-expected-android-external.txt
@@ -1,5 +1,5 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++EditText viewIdResName:"test" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Important stuff My name is Garaventa the weird. (QED) Where are my marbles?"] +++EditText hint:"Important stuff My name is Garaventa the weird. (QED) Where are my marbles?" viewIdResName:"test" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Important stuff My name is Garaventa the weird. (QED) Where are my marbles?"] ++View viewIdResName:"descId" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++TextView text:"My" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++TextView text:" name is" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/aria/aria-alertdialog-expected-android-external.txt b/content/test/data/accessibility/aria/aria-alertdialog-expected-android-external.txt index c3ce97d..af9e965 100644 --- a/content/test/data/accessibility/aria/aria-alertdialog-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-alertdialog-expected-android-external.txt
@@ -1,2 +1,2 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++View actions:[AX_FOCUS] bundle:[chromeRole="alertDialog", roleDescription="alert dialog"] \ No newline at end of file +++View paneTitle:"dialog opened." actions:[AX_FOCUS] bundle:[chromeRole="alertDialog", roleDescription="alert dialog"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-busy-expected-android-external.txt b/content/test/data/accessibility/aria/aria-busy-expected-android-external.txt index cc113f2..779bd928 100644 --- a/content/test/data/accessibility/aria/aria-busy-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-busy-expected-android-external.txt
@@ -1,4 +1,4 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Busy log" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"] ++View text:"Not-busy log" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"] -++TextView actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hint="plain div"] \ No newline at end of file +++TextView hint:"plain div" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hint="plain div"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-combobox-expected-android-external.txt b/content/test/data/accessibility/aria/aria-combobox-expected-android-external.txt index 5887fbd..ecd641108 100644 --- a/content/test/data/accessibility/aria/aria-combobox-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-combobox-expected-android-external.txt
@@ -1,6 +1,6 @@ WebView focusable scrollable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++TextView text:"State" viewIdResName:"state_label" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++EditText canOpenPopUp clickable editable disabled focusable focused inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[CLEAR_FOCUS, CLICK, AX_FOCUS, COLLAPSE] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300", hint="State"] +++EditText hint:"State" canOpenPopUp clickable editable disabled focusable focused inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[CLEAR_FOCUS, CLICK, AX_FOCUS, COLLAPSE] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300", hint="State"] ++ListView viewIdResName:"state_list" stateDescription:"2 items" clickable CollectionInfo:[rows=2, cols=0] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="listBox", clickableScore="300", roleDescription="list box"] ++++View text:"Alabama" viewIdResName:"state1" stateDescription:"in list, item 1 of 2" clickable focusable CollectionItemInfo:[rowIndex=0, rowSpan=0, colIndex=0, colSpan=0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption", clickableScore="200"] ++++View text:"Alaska" viewIdResName:"state2" stateDescription:"in list, item 2 of 2" clickable focusable selected CollectionItemInfo:[rowIndex=1, rowSpan=0, colIndex=0, colSpan=0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption", clickableScore="200"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-combobox-implicit-haspopup-expected-android-external.txt b/content/test/data/accessibility/aria/aria-combobox-implicit-haspopup-expected-android-external.txt index f6ca5f2..db3df51 100644 --- a/content/test/data/accessibility/aria/aria-combobox-implicit-haspopup-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-combobox-implicit-haspopup-expected-android-external.txt
@@ -1,5 +1,5 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"ComboBoxGrouping" canOpenPopUp actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="comboBoxGrouping"] ++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] -++EditText canOpenPopUp clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300", hint="TextFieldWithComboBox"] +++EditText hint:"TextFieldWithComboBox" canOpenPopUp clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300", hint="TextFieldWithComboBox"] ++Spinner text:"ComboBoxMenuButton"" canOpenPopUp clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="comboBoxMenuButton"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-describedby-expected-android-external.txt b/content/test/data/accessibility/aria/aria-describedby-expected-android-external.txt index 9c6e8495..45843907 100644 --- a/content/test/data/accessibility/aria/aria-describedby-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-describedby-expected-android-external.txt
@@ -1,4 +1,4 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++EditText viewIdResName:"username" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Your username should be your email id"] +++EditText hint:"Your username should be your email id" viewIdResName:"username" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Your username should be your email id"] ++View text:"Your username should be your email id" viewIdResName:"username-tip" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tooltip", roleDescription="tooltip"] -++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="mmddyy"] \ No newline at end of file +++EditText hint:"mmddyy" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="mmddyy"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-description-expected-android-external.txt b/content/test/data/accessibility/aria/aria-description-expected-android-external.txt index 29aa175..c9ca931 100644 --- a/content/test/data/accessibility/aria/aria-description-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-description-expected-android-external.txt
@@ -1,4 +1,4 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++TextView text:"description" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="Text-description"] -++TextView text:"both" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="Description from describedby"] +++TextView text:"description" hint:"Text-description" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="Text-description"] +++TextView text:"both" hint:"Description from describedby" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="Description from describedby"] ++View text:"Description from describedby" viewIdResName:"desc1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tooltip", roleDescription="tooltip"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-dialog-expected-android-external.txt b/content/test/data/accessibility/aria/aria-dialog-expected-android-external.txt index 9c9d4e5..6673b514 100644 --- a/content/test/data/accessibility/aria/aria-dialog-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-dialog-expected-android-external.txt
@@ -1,2 +1,2 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++Dialog text:"This is ARIA dialog." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"] \ No newline at end of file +++Dialog text:"This is ARIA dialog." paneTitle:"dialog opened." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-errormessage-expected-android-external.txt b/content/test/data/accessibility/aria/aria-errormessage-expected-android-external.txt index 7de6a108..e595f8eb 100644 --- a/content/test/data/accessibility/aria/aria-errormessage-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-errormessage-expected-android-external.txt
@@ -1,8 +1,8 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Invalid is true"] -++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Invalid is false"] -++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Invalid is not set"] +++++EditText hint:"Invalid is true" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Invalid is true"] +++++EditText hint:"Invalid is false" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Invalid is false"] +++++EditText hint:"Invalid is not set" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Invalid is not set"] ++TextView text:"Error for invalid input" viewIdResName:"error1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++TextView text:"Error for input which is not invalid" viewIdResName:"error2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++TextView text:"Error for input with invalid not set" viewIdResName:"error3" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-hidden-described-by-expected-android-external.txt b/content/test/data/accessibility/aria/aria-hidden-described-by-expected-android-external.txt index afcc236..e114129e 100644 --- a/content/test/data/accessibility/aria/aria-hidden-described-by-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-hidden-described-by-expected-android-external.txt
@@ -1,5 +1,5 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++TextView text:"span-A" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-1"] -++TextView text:"span-B" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-2"] -++TextView text:"span-C" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-3"] -++TextView text:"span-D" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-4"] \ No newline at end of file +++TextView text:"span-A" hint:"span-1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-1"] +++TextView text:"span-B" hint:"span-2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-2"] +++TextView text:"span-C" hint:"span-3" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-3"] +++TextView text:"span-D" hint:"span-4" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-4"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-illegal-val-expected-android-external.txt b/content/test/data/accessibility/aria/aria-illegal-val-expected-android-external.txt index f788cab..bd07fb6 100644 --- a/content/test/data/accessibility/aria/aria-illegal-val-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-illegal-val-expected-android-external.txt
@@ -1,6 +1,6 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View text:"Atomic illegal" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"] -++EditText clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="Autocomplete illegal"] +++EditText hint:"Autocomplete illegal" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="Autocomplete illegal"] ++View text:"Busy illegal" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"] ++View text:"Checked illegal" checkable checked clickable CollectionItemInfo:[rowIndex=0, rowSpan=0, colIndex=0, colSpan=0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="treeItem", roleDescription="tree item"] ++View text:"Current illegal" stateDescription:"current item" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] @@ -11,14 +11,14 @@ ++Button text:"Haspopup illegal" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", roleDescription="button"] ++View text:"Invalid illegal" error:"Invalid entry" contentInvalid actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++View text:"Live illegal" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"] -++Dialog text:"Modal illegal" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"] -++EditText clickable editable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="Multiline illegal"] +++Dialog text:"Modal illegal" paneTitle:"Modal illegal" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"] +++EditText hint:"Multiline illegal" clickable editable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="Multiline illegal"] ++GridView text:"Multiselectable illegal" stateDescription:"multiselectable, none selected." CollectionInfo:[rows=0, cols=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="grid", roleDescription="table"] ++SeekBar text:"50, Orientation illegal" clickable RangeInfo:[current=50.0, min=0.0, max=100.0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] ++ToggleButton text:"Pressed illegal" stateDescription:"On" checkable checked clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="toggleButton", roleDescription="toggle button"] -++EditText clickable editable disabled textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS] bundle:[chromeRole="textField", hint="Readonly illegal"] +++EditText hint:"Readonly illegal" clickable editable disabled textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS] bundle:[chromeRole="textField", hint="Readonly illegal"] ++View text:"Relevant illegal" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="log", roleDescription="log"] -++EditText clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="Required illegal"] +++EditText hint:"Required illegal" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="Required illegal"] ++View stateDescription:"multiselectable, 1 of 1 selected." CollectionInfo:[hierarchical, rows=1, cols=0] actions:[AX_FOCUS] bundle:[chromeRole="tree", roleDescription="tree"] ++++View text:"Selected illegal" clickable selected CollectionItemInfo:[rowIndex=0, rowSpan=0, colIndex=0, colSpan=0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="treeItem", roleDescription="tree item"] ++GridView CollectionInfo:[rows=0, cols=0] actions:[AX_FOCUS] bundle:[chromeRole="grid", roleDescription="table"]
diff --git a/content/test/data/accessibility/aria/aria-labelledby-heading-expected-android-external.txt b/content/test/data/accessibility/aria/aria-labelledby-heading-expected-android-external.txt index c92f85c..48914863 100644 --- a/content/test/data/accessibility/aria/aria-labelledby-heading-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-labelledby-heading-expected-android-external.txt
@@ -1,3 +1,3 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="h2"] +++EditText hint:"h2" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="h2"] ++TextView text:"h2" viewIdResName:"h2" CollectionItemInfo:[heading, rowIndex=0, rowSpan=0, colIndex=0, colSpan=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 2"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-option-complex-children-expected-android-external.txt b/content/test/data/accessibility/aria/aria-option-complex-children-expected-android-external.txt index 24434a81..bf629267 100644 --- a/content/test/data/accessibility/aria/aria-option-complex-children-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-option-complex-children-expected-android-external.txt
@@ -1,7 +1,7 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++ListView stateDescription:"2 items" clickable CollectionInfo:[rows=2, cols=0] actions:[CLICK, AX_FOCUS] bundle:[chromeRole="listBox", roleDescription="list box"] ++++View text:"label-WAI-ARIA 1.1" stateDescription:"in list, item 1 of 2" focusable selected CollectionItemInfo:[rowIndex=0, rowSpan=0, colIndex=0, colSpan=0] actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBoxOption"] -++++++View text:"null" contentDescription:"href-WAI-ARIA 1.1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="title-WAI-ARIA 1.1", roleDescription="link", targetUrl="https://www.w3.org/TR/wai-aria-practices-1.1/"] +++++++View text:"null" hint:"title-WAI-ARIA 1.1" contentDescription:"href-WAI-ARIA 1.1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="title-WAI-ARIA 1.1", roleDescription="link", targetUrl="https://www.w3.org/TR/wai-aria-practices-1.1/"] ++++++++TextView text:"href-WAI-ARIA 1.1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++++TextView text:"title-https://www.w3.org/TR/wai-aria-practices-1.1/" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] ++++++Button text:"Close" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"]
diff --git a/content/test/data/accessibility/aria/aria-readonly-expected-android-external.txt b/content/test/data/accessibility/aria/aria-readonly-expected-android-external.txt index d4b0f622..4cf2ace 100644 --- a/content/test/data/accessibility/aria/aria-readonly-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-readonly-expected-android-external.txt
@@ -5,19 +5,19 @@ ++++EditText text:"Readonly-true input" clickable editable disabled focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="textField", clickableScore="300"] ++TextView text:"Readonly-false plain div" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] ++TextView text:"Readonly-true plain div" focusable actions:[FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++EditText clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="Readonly-false contenteditable div"] -++EditText clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="Readonly-true contenteditable div"] -++EditText clickable editable focusable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="Readonly-false role unimplemented textbox"] -++EditText clickable editable disabled focusable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="textField", hint="Readonly-true role unimplemented textbox"] -++EditText clickable editable focusable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="Readonly-false contenteditable textbox"] -++EditText clickable editable disabled focusable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="textField", hint="Readonly-true contenteditable textbox"] +++EditText hint:"Readonly-false contenteditable div" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="Readonly-false contenteditable div"] +++EditText hint:"Readonly-true contenteditable div" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="Readonly-true contenteditable div"] +++EditText hint:"Readonly-false role unimplemented textbox" clickable editable focusable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="Readonly-false role unimplemented textbox"] +++EditText hint:"Readonly-true role unimplemented textbox" clickable editable disabled focusable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="textField", hint="Readonly-true role unimplemented textbox"] +++EditText hint:"Readonly-false contenteditable textbox" clickable editable focusable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="Readonly-false contenteditable textbox"] +++EditText hint:"Readonly-true contenteditable textbox" clickable editable disabled focusable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="textField", hint="Readonly-true contenteditable textbox"] ++CheckBox text:"Readonly checkbox" checkable clickable disabled actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", roleDescription="checkbox"] -++EditText canOpenPopUp clickable editable disabled focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300", hint="Readonly combobox"] +++EditText hint:"Readonly combobox" canOpenPopUp clickable editable disabled focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300", hint="Readonly combobox"] ++ListView text:"Readonly listbox" clickable disabled CollectionInfo:[rows=0, cols=0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="listBox", roleDescription="list box"] ++View text:"Readonly radiogroup" disabled actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="radioGroup", roleDescription="radio group"] ++SeekBar text:"50, Readonly slider" clickable disabled RangeInfo:[current=50.0, min=0.0, max=100.0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] ++EditText text:"0, Readonly spinbutton" clickable disabled RangeInfo:[current=0.0, min=0.0, max=0.0] actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, SET_PROGRESS] bundle:[chromeRole="spinButton", roleDescription="spin button"] ++MenuItem text:"Readonly menuitemcheckbox" checkable clickable disabled actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItemCheckBox", roleDescription="checkbox"] ++MenuItem text:"Readonly menuitemradio" checkable clickable disabled actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="menuItemRadio", roleDescription="radio button"] -++EditText clickable editable disabled textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS] bundle:[chromeRole="searchBox", hint="Readonly searchbox", roleDescription="search text field"] +++EditText hint:"Readonly searchbox" clickable editable disabled textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS] bundle:[chromeRole="searchBox", hint="Readonly searchbox", roleDescription="search text field"] ++ToggleButton text:"Readonly switch" checkable clickable disabled actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="switch", roleDescription="switch"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-textbox-with-aria-textbox-child-expected-android-external.txt b/content/test/data/accessibility/aria/aria-textbox-with-aria-textbox-child-expected-android-external.txt index abea14f..4d3b6102 100644 --- a/content/test/data/accessibility/aria/aria-textbox-with-aria-textbox-child-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-textbox-with-aria-textbox-child-expected-android-external.txt
@@ -1,9 +1,9 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++EditText text:"Foo\nBar\nBar\nBaz\nBaz" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="not editable"] +++EditText text:"Foo\nBar\nBar\nBaz\nBaz" hint:"not editable" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="not editable"] ++++TextView text:"Foo" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] -++++EditText text:"Bar" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="nested, not editable, rich"] +++++EditText text:"Bar" hint:"nested, not editable, rich" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="nested, not editable, rich"] ++++++TextView text:"Bar" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] -++++EditText text:"Bar" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="nested, not editable, plain"] -++++EditText text:"Baz" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="nested, editable, rich"] -++++EditText text:"Baz" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="nested, editable, plain"] -++EditText text:"Foo\nBar\nBar\nBaz\nBaz" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="editable"] \ No newline at end of file +++++EditText text:"Bar" hint:"nested, not editable, plain" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="nested, not editable, plain"] +++++EditText text:"Baz" hint:"nested, editable, rich" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="nested, editable, rich"] +++++EditText text:"Baz" hint:"nested, editable, plain" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="nested, editable, plain"] +++EditText text:"Foo\nBar\nBar\nBaz\nBaz" hint:"editable" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="editable"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-textbox-with-non-text-children-expected-android-external.txt b/content/test/data/accessibility/aria/aria-textbox-with-non-text-children-expected-android-external.txt index e8646e7..39a81ae 100644 --- a/content/test/data/accessibility/aria/aria-textbox-with-non-text-children-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-textbox-with-non-text-children-expected-android-external.txt
@@ -1,5 +1,5 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] -++EditText text:"focusable: oklink name: \n" clickable editable focusable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="not editable"] +++EditText text:"focusable: oklink name: \n" hint:"not editable" clickable editable focusable textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="not editable"] ++++TextView text:"focusable: " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++Button text:"ok" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++++View text:"null" contentDescription:"link" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/aria/aria-textbox-with-non-text-children.html#"] @@ -7,8 +7,8 @@ ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="labelText"] ++++++TextView text:"name: " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="name:"] -++EditText text:"focusable: oklink name: \n" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="editable"] +++++++EditText hint:"name:" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="name:"] +++EditText text:"focusable: oklink name: \n" hint:"editable" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="editable"] ++++TextView text:"focusable: " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++Button text:"ok" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++++View text:"null" contentDescription:"link" clickable actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/aria/aria-textbox-with-non-text-children.html#"] @@ -16,8 +16,8 @@ ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="labelText", clickableScore="100"] ++++++TextView text:"name: " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="name:"] -++EditText text:"focusable: oklink name: \n" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="not editable or focusable"] +++++++EditText hint:"name:" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="name:"] +++EditText text:"focusable: oklink name: \n" hint:"not editable or focusable" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hint="not editable or focusable"] ++++TextView text:"focusable: " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++Button text:"ok" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++++View text:"null" contentDescription:"link" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/aria/aria-textbox-with-non-text-children.html#"] @@ -25,6 +25,6 @@ ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="labelText"] ++++++TextView text:"name: " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="name:"] -++EditText clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hasImage="true", hint="not editable, img child"] +++++++EditText hint:"name:" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="name:"] +++EditText hint:"not editable, img child" clickable editable textSelectionStart:0 textSelectionEnd:0 actions:[CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", hasImage="true", hint="not editable, img child"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="image", hasImage="true", roleDescription="graphic"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-tooltip-expected-android-external.txt b/content/test/data/accessibility/aria/aria-tooltip-expected-android-external.txt index d263369..2450421 100644 --- a/content/test/data/accessibility/aria/aria-tooltip-expected-android-external.txt +++ b/content/test/data/accessibility/aria/aria-tooltip-expected-android-external.txt
@@ -1,3 +1,3 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++EditText viewIdResName:"username" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Your username should be your email id"] +++EditText hint:"Your username should be your email id" viewIdResName:"username" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Your username should be your email id"] ++View text:"Your username should be your email id" viewIdResName:"username-tip" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="tooltip", roleDescription="tooltip"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/aria-two-owners-remove-one-expected-auralinux.txt b/content/test/data/accessibility/aria/aria-two-owners-remove-one-expected-auralinux.txt new file mode 100644 index 0000000..e0864395 --- /dev/null +++ b/content/test/data/accessibility/aria/aria-two-owners-remove-one-expected-auralinux.txt
@@ -0,0 +1,8 @@ +[document web] name='done' +++[section] +++++[section] +++++++[landmark] name='owner2' +++++++++[section] +++++++++++[push button] name='1' +++[static] name='"' +++[static] name='"'
diff --git a/content/test/data/accessibility/aria/aria-two-owners-remove-one-expected-blink.txt b/content/test/data/accessibility/aria/aria-two-owners-remove-one-expected-blink.txt new file mode 100644 index 0000000..5326121 --- /dev/null +++ b/content/test/data/accessibility/aria/aria-two-owners-remove-one-expected-blink.txt
@@ -0,0 +1,19 @@ +rootWebArea name='done' +++genericContainer ignored +++++genericContainer ignored +++++++genericContainer +++++++++genericContainer +++++++++++region name='owner2' +++++++++++++genericContainer +++++++++++++++button name='1' +++++++++++++++++staticText name='1' +++++++++++++++++++inlineTextBox name='1' +++++++genericContainer ignored +++++++++genericContainer ignored +++++++++++genericContainer ignored +++++++++++++staticText name='"' +++++++++++++++inlineTextBox name='"' +++++++++genericContainer ignored +++++++++++genericContainer ignored +++++++++++++staticText name='"' +++++++++++++++inlineTextBox name='"'
diff --git a/content/test/data/accessibility/aria/aria-two-owners-remove-one.html b/content/test/data/accessibility/aria/aria-two-owners-remove-one.html new file mode 100644 index 0000000..bec18509 --- /dev/null +++ b/content/test/data/accessibility/aria/aria-two-owners-remove-one.html
@@ -0,0 +1,45 @@ +<!-- +@WAIT-FOR:done +--> + +<div id="root"> + <div id="ownerParent"></div> + <div id="ownedLayer"> + <button id="btn1" role="button" aria-label="1" aria-disabled="false">1</button> + </div> +</div> + + +<q></q> +<style> +.no_quote q::before { content: no-close-quote; } +</style> +<script> + function addOwnersStep() { + let ownerElement = document.createElement('article'); + ownerElement.setAttribute("id", "owner1"); + ownerElement.setAttribute("aria-label", "owner1"); + ownerElement.setAttribute("role", "region"); + ownerElement.setAttribute("aria-owns", "ownedLayer"); + ownerParent.appendChild(ownerElement); + + let ownerElement2 = document.createElement('article'); + ownerElement2.setAttribute("id", "owner2"); + ownerElement2.setAttribute("aria-label", "owner2"); + ownerElement2.setAttribute("role", "region"); + ownerElement2.setAttribute("aria-owns", "ownedLayer"); + ownerParent.appendChild(ownerElement2); + + setTimeout(removeOwnerStep, 100); + } + function removeOwnerStep() { + let owner = document.getElementById("owner1"); + owner.remove(); + setTimeout(() => { + document.title = 'done'; + }, 100) + } + window.addEventListener("load", () => { + setTimeout(addOwnersStep, 100); + }); +</script>
diff --git a/content/test/data/accessibility/aria/hidden-described-by-expected-android-external.txt b/content/test/data/accessibility/aria/hidden-described-by-expected-android-external.txt index dec360a..b5837a6c8 100644 --- a/content/test/data/accessibility/aria/hidden-described-by-expected-android-external.txt +++ b/content/test/data/accessibility/aria/hidden-described-by-expected-android-external.txt
@@ -1,4 +1,4 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++TextView text:"span-A3" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-A4"] -++TextView text:"span-B" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-A2"] +++TextView text:"span-A3" hint:"span-A4" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-A4"] +++TextView text:"span-B" hint:"span-A2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer", hint="span-A2"] ++TextView text:"span-C" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/hidden-expected-android-external.txt b/content/test/data/accessibility/aria/hidden-expected-android-external.txt index 04c7db0..0c5f53b 100644 --- a/content/test/data/accessibility/aria/hidden-expected-android-external.txt +++ b/content/test/data/accessibility/aria/hidden-expected-android-external.txt
@@ -1,3 +1,3 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++TextView actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hint="b"] -++TextView actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hint="c"] \ No newline at end of file +++TextView hint:"b" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hint="b"] +++TextView hint:"c" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hint="c"] \ No newline at end of file
diff --git a/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-android-external.txt b/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-android-external.txt index 06a8df6..579aa61 100644 --- a/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-android-external.txt +++ b/content/test/data/accessibility/aria/input-text-aria-placeholder-expected-android-external.txt
@@ -1,8 +1,8 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-placeholder1"] -++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="placeholder2"] -++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-label3 placeholder3"] -++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-label4 aria-placeholder4"] -++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-label5 placeholder5 aria-description5"] +++EditText hint:"aria-placeholder1" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-placeholder1"] +++EditText hint:"placeholder2" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="placeholder2"] +++EditText hint:"aria-label3 placeholder3" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-label3 placeholder3"] +++EditText hint:"aria-label4 aria-placeholder4" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-label4 aria-placeholder4"] +++EditText hint:"aria-label5 placeholder5 aria-description5" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-label5 placeholder5 aria-description5"] ++TextView text:"aria-description5" viewIdResName:"ariadesc5" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] -++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-placeholder6 title6"] \ No newline at end of file +++EditText hint:"aria-placeholder6 title6" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="aria-placeholder6 title6"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/a-name-calc-expected-android-external.txt b/content/test/data/accessibility/html/a-name-calc-expected-android-external.txt index 2fa6e09..45561e6 100644 --- a/content/test/data/accessibility/html/a-name-calc-expected-android-external.txt +++ b/content/test/data/accessibility/html/a-name-calc-expected-android-external.txt
@@ -2,7 +2,7 @@ ++View text:"null" contentDescription:"InnerText0" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/a-name-calc.html#"] ++++TextView text:"InnerText0" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++View text:"null" contentDescription:"InnerText1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Title1", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/a-name-calc.html#"] +++View text:"null" hint:"Title1" contentDescription:"InnerText1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Title1", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/a-name-calc.html#"] ++++TextView text:"InnerText1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++View text:"null" contentDescription:"Title2" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/a-name-calc.html#"]
diff --git a/content/test/data/accessibility/html/actions-expected-android-external.txt b/content/test/data/accessibility/html/actions-expected-android-external.txt index 29779fb..448237f 100644 --- a/content/test/data/accessibility/html/actions-expected-android-external.txt +++ b/content/test/data/accessibility/html/actions-expected-android-external.txt
@@ -1,4 +1,4 @@ WebView text:"Actions" focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++SeekBar text:"50" clickable focusable RangeInfo:[current=50.0, min=1.0, max=100.0] actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, SCROLL_FORWARD, SCROLL_BACKWARD, SET_PROGRESS] bundle:[chromeRole="slider", roleDescription="slider"] -++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Test textfield"] \ No newline at end of file +++++EditText hint:"Test textfield" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Test textfield"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/button-name-calc-expected-android-external.txt b/content/test/data/accessibility/html/button-name-calc-expected-android-external.txt index 9981138f..9ce15e6 100644 --- a/content/test/data/accessibility/html/button-name-calc-expected-android-external.txt +++ b/content/test/data/accessibility/html/button-name-calc-expected-android-external.txt
@@ -1,10 +1,10 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++Button text:"InnerText0" viewIdResName:"c0" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] -++Button text:"InnerText1" viewIdResName:"c1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="Title1", roleDescription="button"] -++Button text:"AriaLabel2" viewIdResName:"c2" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="Title2", roleDescription="button"] -++Button text:"LabelledBy3" viewIdResName:"c3" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="Title3", roleDescription="button"] -++Button text:"LabelledBy4" viewIdResName:"c4" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="DescribedBy4", roleDescription="button"] -++Button text:"InnerText5" viewIdResName:"c5" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="DescribedBy5", roleDescription="button"] +++Button text:"InnerText1" hint:"Title1" viewIdResName:"c1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="Title1", roleDescription="button"] +++Button text:"AriaLabel2" hint:"Title2" viewIdResName:"c2" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="Title2", roleDescription="button"] +++Button text:"LabelledBy3" hint:"Title3" viewIdResName:"c3" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="Title3", roleDescription="button"] +++Button text:"LabelledBy4" hint:"DescribedBy4" viewIdResName:"c4" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="DescribedBy4", roleDescription="button"] +++Button text:"InnerText5" hint:"DescribedBy5" viewIdResName:"c5" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="DescribedBy5", roleDescription="button"] ++Button text:"Outer inner" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++Button text:"Outer inner1" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] ++Button text:"Outer grandchild" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"]
diff --git a/content/test/data/accessibility/html/canvas-fallback-expected-android-external.txt b/content/test/data/accessibility/html/canvas-fallback-expected-android-external.txt index 019b0e83..2e651b7 100644 --- a/content/test/data/accessibility/html/canvas-fallback-expected-android-external.txt +++ b/content/test/data/accessibility/html/canvas-fallback-expected-android-external.txt
@@ -3,9 +3,9 @@ ++++Image text:"Static fallback" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="canvas", hasImage="true"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="canvas", hasImage="true"] ++++++TextView text:"\n " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++++TextView text:"Line breaking content in a fallback" viewIdResName:"p1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph", hint="Aria hidden paragraph in fallback content"] +++++++TextView text:"Line breaking content in a fallback" hint:"Aria hidden paragraph in fallback content" viewIdResName:"p1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph", hint="Aria hidden paragraph in fallback content"] ++++++TextView text:"\n " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++++TextView text:"This is another paragraph in fallback" viewIdResName:"p2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph", hint="Visibility hidden paragraph in fallback content"] +++++++TextView text:"This is another paragraph in fallback" hint:"Visibility hidden paragraph in fallback content" viewIdResName:"p2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph", hint="Visibility hidden paragraph in fallback content"] ++++++TextView text:"\n " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++++TextView text:"Aria hidden paragraph in fallback content" viewIdResName:"h1" notVisibleToUser CollectionItemInfo:[heading, rowIndex=0, rowSpan=0, colIndex=0, colSpan=0] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="heading", roleDescription="heading 1"] ++++++TextView text:"\n " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/caption-expected-android-external.txt b/content/test/data/accessibility/html/caption-expected-android-external.txt index d4f7401..82d72db0 100644 --- a/content/test/data/accessibility/html/caption-expected-android-external.txt +++ b/content/test/data/accessibility/html/caption-expected-android-external.txt
@@ -10,7 +10,7 @@ ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"Safari" CollectionItemInfo:[rowIndex=2, rowSpan=1, colIndex=0, colSpan=1] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="cell"] ++++++View text:"WebKit" CollectionItemInfo:[rowIndex=2, rowSpan=1, colIndex=1, colSpan=1] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="cell"] -++GridView text:"Name" CollectionInfo:[rows=1, cols=2] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="table", hint="Description", roleDescription="table"] +++GridView text:"Name" hint:"Description" CollectionInfo:[rows=1, cols=2] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="table", hint="Description", roleDescription="table"] ++++View text:"Description" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="caption"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="row"] ++++++View text:"A" CollectionItemInfo:[rowIndex=0, rowSpan=1, colIndex=0, colSpan=1] actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="cell"]
diff --git a/content/test/data/accessibility/html/checkbox-name-calc-expected-android-external.txt b/content/test/data/accessibility/html/checkbox-name-calc-expected-android-external.txt index da6b79b..507d9340 100644 --- a/content/test/data/accessibility/html/checkbox-name-calc-expected-android-external.txt +++ b/content/test/data/accessibility/html/checkbox-name-calc-expected-android-external.txt
@@ -1,10 +1,10 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++CheckBox text:"Title0" viewIdResName:"c0" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", roleDescription="checkbox"] -++CheckBox text:"Label1" viewIdResName:"c1" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="Title1", roleDescription="checkbox"] -++CheckBox text:"AriaLabel2" viewIdResName:"c2" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="Title2", roleDescription="checkbox"] -++CheckBox text:"LabelledBy3" viewIdResName:"c3" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="Title3", roleDescription="checkbox"] -++CheckBox text:"LabelledBy4" viewIdResName:"c4" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="DescribedBy4", roleDescription="checkbox"] -++CheckBox viewIdResName:"c5" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="DescribedBy5", roleDescription="checkbox"] +++CheckBox text:"Label1" hint:"Title1" viewIdResName:"c1" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="Title1", roleDescription="checkbox"] +++CheckBox text:"AriaLabel2" hint:"Title2" viewIdResName:"c2" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="Title2", roleDescription="checkbox"] +++CheckBox text:"LabelledBy3" hint:"Title3" viewIdResName:"c3" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="Title3", roleDescription="checkbox"] +++CheckBox text:"LabelledBy4" hint:"DescribedBy4" viewIdResName:"c4" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="DescribedBy4", roleDescription="checkbox"] +++CheckBox hint:"DescribedBy5" viewIdResName:"c5" checkable clickable focusable actions:[FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="checkBox", clickableScore="300", hint="DescribedBy5", roleDescription="checkbox"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] ++++View text:"Label2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="labelText"]
diff --git a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-android-external.txt b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-android-external.txt index 3ad28d27..d399e23e 100644 --- a/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-android-external.txt +++ b/content/test/data/accessibility/html/contenteditable-with-no-descendants-expected-android-external.txt
@@ -1,5 +1,5 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++EditText clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="label"] -++EditText clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="description"] -++EditText clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="title"] +++EditText hint:"label" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="label"] +++EditText hint:"description" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="description"] +++EditText hint:"title" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="genericContainer", clickableScore="200", hint="title"] ++TextView text:"description" viewIdResName:"description" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="paragraph"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/dialog-expected-android-external.txt b/content/test/data/accessibility/html/dialog-expected-android-external.txt index 9f74902..0faee2b 100644 --- a/content/test/data/accessibility/html/dialog-expected-android-external.txt +++ b/content/test/data/accessibility/html/dialog-expected-android-external.txt
@@ -1,2 +1,2 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++Dialog text:"Text in dialog" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"] \ No newline at end of file +++Dialog text:"Text in dialog" paneTitle:"dialog opened." actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="dialog", roleDescription="dialog"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-button-expected-android-external.txt b/content/test/data/accessibility/html/input-button-expected-android-external.txt index 8198032..ab7ced1 100644 --- a/content/test/data/accessibility/html/input-button-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-button-expected-android-external.txt
@@ -1,4 +1,4 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Button text:"Button" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", roleDescription="button"] -++++Button text:"Name" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="Description", roleDescription="button"] \ No newline at end of file +++++Button text:"Name" hint:"Description" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="button", clickableScore="300", hint="Description", roleDescription="button"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-date-expected-android-external.txt b/content/test/data/accessibility/html/input-date-expected-android-external.txt index 653cbe0..fc430fe 100644 --- a/content/test/data/accessibility/html/input-date-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-date-expected-android-external.txt
@@ -1,4 +1,4 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", roleDescription="date picker"] -++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", hint="When", roleDescription="date picker"] \ No newline at end of file +++++Spinner text:"2008-09-01" hint:"When" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", hint="When", roleDescription="date picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-android-external.txt b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-android-external.txt index 34d7a75..96460d74 100644 --- a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-expected-android-external.txt
@@ -2,4 +2,4 @@ ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", roleDescription="date picker"] ++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", roleDescription="date picker"] -++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", hint="Third date picker", roleDescription="date picker"] \ No newline at end of file +++++Spinner text:"2008-09-01" hint:"Third date picker" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", hint="Third date picker", roleDescription="date picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-android-external.txt b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-android-external.txt index 34d7a75..96460d74 100644 --- a/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-date-with-popup-open-multiple-for-win-expected-android-external.txt
@@ -2,4 +2,4 @@ ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", roleDescription="date picker"] ++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", roleDescription="date picker"] -++++Spinner text:"2008-09-01" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", hint="Third date picker", roleDescription="date picker"] \ No newline at end of file +++++Spinner text:"2008-09-01" hint:"Third date picker" clickable focusable inputType:20 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="date", clickableScore="300", hint="Third date picker", roleDescription="date picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-datetime-expected-android-external.txt b/content/test/data/accessibility/html/input-datetime-expected-android-external.txt index fe9d6d0..d8fc6b5 100644 --- a/content/test/data/accessibility/html/input-datetime-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-datetime-expected-android-external.txt
@@ -1,4 +1,4 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++EditText text:"1/1/2015 1:00AM" clickable editable focusable inputType:4 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300"] -++++EditText text:"1/1/2015 1:00AM" clickable editable focusable inputType:4 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Launch"] \ No newline at end of file +++++EditText text:"1/1/2015 1:00AM" hint:"Launch" clickable editable focusable inputType:4 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Launch"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-list-expected-android-external.txt b/content/test/data/accessibility/html/input-list-expected-android-external.txt index f1834c4..5329ccb 100644 --- a/content/test/data/accessibility/html/input-list-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-list-expected-android-external.txt
@@ -2,4 +2,4 @@ ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View actions:[AX_FOCUS] bundle:[chromeRole="labelText"] ++++++TextView text:"Choose a pokemon " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++++EditText canOpenPopUp clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300", hint="Choose a pokemon"] \ No newline at end of file +++++++EditText hint:"Choose a pokemon" canOpenPopUp clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textFieldWithComboBox", clickableScore="300", hint="Choose a pokemon"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-text-expected-android-external.txt b/content/test/data/accessibility/html/input-text-expected-android-external.txt index 7541aee7..7a0f820 100644 --- a/content/test/data/accessibility/html/input-text-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-text-expected-android-external.txt
@@ -1,3 +1,3 @@ WebView focusable scrollable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++EditText clickable editable focusable focused inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[CLEAR_FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Name"] \ No newline at end of file +++++EditText hint:"Name" clickable editable focusable focused inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[CLEAR_FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Name"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-text-name-calc-expected-android-external.txt b/content/test/data/accessibility/html/input-text-name-calc-expected-android-external.txt index b42de60..f136c48 100644 --- a/content/test/data/accessibility/html/input-text-name-calc-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-text-name-calc-expected-android-external.txt
@@ -1,14 +1,14 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++EditText viewIdResName:"c0" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Title0"] -++EditText viewIdResName:"c1" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Label1 Title1"] -++EditText viewIdResName:"c2" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="AriaLabel2 Title2"] -++EditText viewIdResName:"c3" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="LabelledBy3 Title3"] -++EditText viewIdResName:"c4" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Placeholder4"] -++EditText viewIdResName:"c4a" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="ARIA Placeholder4a"] -++EditText viewIdResName:"c4b" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Placeholder4b"] -++EditText viewIdResName:"c5" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Placeholder5 Title5"] -++EditText viewIdResName:"c6" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="LabelledBy6 DescribedBy6"] -++EditText viewIdResName:"c7" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="AriaLabel7 Placeholder7 DescribedBy7"] +++EditText hint:"Title0" viewIdResName:"c0" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Title0"] +++EditText hint:"Label1 Title1" viewIdResName:"c1" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Label1 Title1"] +++EditText hint:"AriaLabel2 Title2" viewIdResName:"c2" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="AriaLabel2 Title2"] +++EditText hint:"LabelledBy3 Title3" viewIdResName:"c3" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="LabelledBy3 Title3"] +++EditText hint:"Placeholder4" viewIdResName:"c4" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Placeholder4"] +++EditText hint:"ARIA Placeholder4a" viewIdResName:"c4a" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="ARIA Placeholder4a"] +++EditText hint:"Placeholder4b" viewIdResName:"c4b" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Placeholder4b"] +++EditText hint:"Placeholder5 Title5" viewIdResName:"c5" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Placeholder5 Title5"] +++EditText hint:"LabelledBy6 DescribedBy6" viewIdResName:"c6" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="LabelledBy6 DescribedBy6"] +++EditText hint:"AriaLabel7 Placeholder7 DescribedBy7" viewIdResName:"c7" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="AriaLabel7 Placeholder7 DescribedBy7"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++View text:"Label1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="labelText"] ++++TextView text:" " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"]
diff --git a/content/test/data/accessibility/html/input-text-read-only-expected-android-external.txt b/content/test/data/accessibility/html/input-text-read-only-expected-android-external.txt index 5c74ca1..80f50f4 100644 --- a/content/test/data/accessibility/html/input-text-read-only-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-text-read-only-expected-android-external.txt
@@ -1,3 +1,3 @@ WebView focusable scrollable actions:[FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++EditText clickable editable disabled focusable focused inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[CLEAR_FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="textField", clickableScore="300", hint="Name"] \ No newline at end of file +++++EditText hint:"Name" clickable editable disabled focusable focused inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[CLEAR_FOCUS, CLICK, AX_FOCUS] bundle:[chromeRole="textField", clickableScore="300", hint="Name"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-text-value-expected-android-external.txt b/content/test/data/accessibility/html/input-text-value-expected-android-external.txt index ade67af..caf5c293 100644 --- a/content/test/data/accessibility/html/input-text-value-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-text-value-expected-android-external.txt
@@ -1,15 +1,15 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++View text:"l1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="labelText"] -++++EditText viewIdResName:"i1" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l1"] +++++EditText hint:"l1" viewIdResName:"i1" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l1"] ++++View text:"l2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="labelText"] -++++EditText text:"value" viewIdResName:"i2" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l2"] -++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l2"] -++++EditText text:"value *" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l2"] +++++EditText text:"value" hint:"l2" viewIdResName:"i2" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l2"] +++++EditText hint:"l2" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l2"] +++++EditText text:"value *" hint:"l2" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l2"] ++++View text:"Email" viewIdResName:"l3" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="labelText"] ++++TextView viewIdResName:"l4" actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] -++++EditText clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Email"] -++++EditText text:"value" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Email"] -++++EditText clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l5"] -++++EditText text:"Value" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l6"] -++++EditText text:"value" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Name Description"] \ No newline at end of file +++++EditText hint:"Email" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Email"] +++++EditText text:"value" hint:"Email" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Email"] +++++EditText hint:"l5" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, PASTE, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l5"] +++++EditText text:"Value" hint:"l6" clickable editable focusable multiLine textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="l6"] +++++EditText text:"value" hint:"Name Description" clickable editable focusable inputType:1 textSelectionStart:0 textSelectionEnd:0 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, COPY, PASTE, CUT, SET_SELECTION, SET_TEXT, IME_ENTER] bundle:[chromeRole="textField", clickableScore="300", hint="Name Description"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/input-time-expected-android-external.txt b/content/test/data/accessibility/html/input-time-expected-android-external.txt index 36df1fa..0d38378d 100644 --- a/content/test/data/accessibility/html/input-time-expected-android-external.txt +++ b/content/test/data/accessibility/html/input-time-expected-android-external.txt
@@ -1,4 +1,4 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer"] ++++Spinner text:"00:00:00" clickable focusable inputType:36 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="inputTime", clickableScore="300", roleDescription="time picker"] -++++Spinner text:"00:00:00" clickable focusable inputType:36 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="inputTime", clickableScore="300", hint="Breakfast", roleDescription="time picker"] \ No newline at end of file +++++Spinner text:"00:00:00" hint:"Breakfast" clickable focusable inputType:36 actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="inputTime", clickableScore="300", hint="Breakfast", roleDescription="time picker"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/ruby-expected-android-external.txt b/content/test/data/accessibility/html/ruby-expected-android-external.txt index 54027b91..3b797cc 100644 --- a/content/test/data/accessibility/html/ruby-expected-android-external.txt +++ b/content/test/data/accessibility/html/ruby-expected-android-external.txt
@@ -1,7 +1,7 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea"] -++View text:"ruby base" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="ruby", hint="ruby text"] +++View text:"ruby base" hint:"ruby text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="ruby", hint="ruby text"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] -++++View text:"ruby base" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="ruby", hint="ruby text"] +++++View text:"ruby base" hint:"ruby text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="ruby", hint="ruby text"] ++View actions:[AX_FOCUS] bundle:[chromeRole="paragraph"] ++++TextView text:"Hi! " actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="staticText"] -++++View text:"ruby base" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="ruby", hint="ruby text"] \ No newline at end of file +++++View text:"ruby base" hint:"ruby text" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="ruby", hint="ruby text"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/summary-expected-android-external.txt b/content/test/data/accessibility/html/summary-expected-android-external.txt index 1fad624e..2232fc3 100644 --- a/content/test/data/accessibility/html/summary-expected-android-external.txt +++ b/content/test/data/accessibility/html/summary-expected-android-external.txt
@@ -2,4 +2,4 @@ ++View actions:[AX_FOCUS] bundle:[chromeRole="details"] ++++View text:"details tag" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="disclosureTriangle", clickableScore="300", roleDescription="disclosure triangle"] ++View actions:[AX_FOCUS] bundle:[chromeRole="details"] -++++View text:"name" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="disclosureTriangle", clickableScore="300", hint="details #2", roleDescription="disclosure triangle"] \ No newline at end of file +++++View text:"name" hint:"details #2" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS, EXPAND] bundle:[chromeRole="disclosureTriangle", clickableScore="300", hint="details #2", roleDescription="disclosure triangle"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-desc-in-group-expected-android-external.txt b/content/test/data/accessibility/html/svg-desc-in-group-expected-android-external.txt index 4f2814a..c8bc6ffd 100644 --- a/content/test/data/accessibility/html/svg-desc-in-group-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-desc-in-group-expected-android-external.txt
@@ -1,5 +1,5 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View actions:[AX_FOCUS] bundle:[chromeRole="group", hint="Group with circle and text"] +++++++View hint:"Group with circle and text" actions:[AX_FOCUS] bundle:[chromeRole="group", hint="Group with circle and text"] ++++++++TextView text:"hello world" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-expected-android-external.txt b/content/test/data/accessibility/html/svg-expected-android-external.txt index 0ac6bf1..d224d281 100644 --- a/content/test/data/accessibility/html/svg-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-expected-android-external.txt
@@ -1,4 +1,4 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] -++++Image text:"svg" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="svgRoot", hasImage="true", hint="SVG Title Tag", roleDescription="graphic"] +++++Image text:"svg" hint:"SVG Title Tag" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="svgRoot", hasImage="true", hint="SVG Title Tag", roleDescription="graphic"] ++++++TextView text:"Test" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="genericContainer"] \ No newline at end of file
diff --git a/content/test/data/accessibility/html/svg-text-alternative-computation-expected-android-external.txt b/content/test/data/accessibility/html/svg-text-alternative-computation-expected-android-external.txt index 887d5b8..a058d8d 100644 --- a/content/test/data/accessibility/html/svg-text-alternative-computation-expected-android-external.txt +++ b/content/test/data/accessibility/html/svg-text-alternative-computation-expected-android-external.txt
@@ -1,11 +1,11 @@ WebView focusable focused scrollable actions:[CLEAR_FOCUS, AX_FOCUS] bundle:[chromeRole="rootWebArea", hasImage="true"] ++View actions:[AX_FOCUS] bundle:[chromeRole="genericContainer", hasImage="true"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View text:"null" contentDescription:"Link (from aria-labelledby)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from title)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] +++++++View text:"null" hint:"Link (from title)" contentDescription:"Link (from aria-labelledby)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from title)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View text:"null" contentDescription:"Link (from aria-label)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from title)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] +++++++View text:"null" hint:"Link (from title)" contentDescription:"Link (from aria-label)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from title)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View text:"null" contentDescription:"Link (from title)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from xlink:title)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] +++++++View text:"null" hint:"Link (from xlink:title)" contentDescription:"Link (from title)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from xlink:title)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] ++++++View text:"null" contentDescription:"Link (from xlink:title)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] @@ -21,21 +21,21 @@ ++++++View text:"Rectangle Symbol (From symbol's title)" viewIdResName:"myRect" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++++++View text:"Rectangle Symbol (From symbol's title)" viewIdResName:"myRect" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="group"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View text:"null" contentDescription:"Link (from title)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from aria-describedby)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] +++++++View text:"null" hint:"Link (from aria-describedby)" contentDescription:"Link (from title)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from aria-describedby)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View text:"null" contentDescription:"Link (from title)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from aria-description)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] +++++++View text:"null" hint:"Link (from aria-description)" contentDescription:"Link (from title)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from aria-description)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View text:"null" contentDescription:"Link (from title)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from desc)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] +++++++View text:"null" hint:"Link (from desc)" contentDescription:"Link (from title)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from desc)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View text:"null" contentDescription:"Link (from aria-label)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from title)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] +++++++View text:"null" hint:"Link (from title)" contentDescription:"Link (from aria-label)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from title)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View text:"null" contentDescription:"Link (from title)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from xlink:title)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] +++++++View text:"null" hint:"Link (from xlink:title)" contentDescription:"Link (from title)" clickable focusable actions:[FOCUS, CLICK, AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="link", clickableScore="300", hint="Link (from xlink:title)", roleDescription="link", targetUrl="file:///storage/emulated/0/chromium_tests_root/content/test/data/accessibility/html/foo.html"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View actions:[AX_FOCUS] bundle:[chromeRole="graphicsObject", hint="Circle (From first use element's desc)", roleDescription="graphics object"] -++++++View actions:[AX_FOCUS] bundle:[chromeRole="graphicsObject", hint="Circle (From second use element's desc)", roleDescription="graphics object"] +++++++View hint:"Circle (From first use element's desc)" actions:[AX_FOCUS] bundle:[chromeRole="graphicsObject", hint="Circle (From first use element's desc)", roleDescription="graphics object"] +++++++View hint:"Circle (From second use element's desc)" actions:[AX_FOCUS] bundle:[chromeRole="graphicsObject", hint="Circle (From second use element's desc)", roleDescription="graphics object"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View text:"Circle 1" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="graphicsObject", hint="Circle (From first use element's title)", roleDescription="graphics object"] -++++++View text:"Circle 2" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="graphicsObject", hint="Circle (From second use element's title)", roleDescription="graphics object"] +++++++View text:"Circle 1" hint:"Circle (From first use element's title)" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="graphicsObject", hint="Circle (From first use element's title)", roleDescription="graphics object"] +++++++View text:"Circle 2" hint:"Circle (From second use element's title)" actions:[AX_FOCUS, NEXT, PREVIOUS] bundle:[chromeRole="graphicsObject", hint="Circle (From second use element's title)", roleDescription="graphics object"] ++++Image actions:[AX_FOCUS] bundle:[chromeRole="svgRoot", hasImage="true", roleDescription="graphic"] -++++++View viewIdResName:"myRect2" actions:[AX_FOCUS] bundle:[chromeRole="group", hint="Rectangle Symbol (From symbol's desc)"] -++++++View viewIdResName:"myRect2" actions:[AX_FOCUS] bundle:[chromeRole="group", hint="Rectangle Symbol (From symbol's desc)"] \ No newline at end of file +++++++View hint:"Rectangle Symbol (From symbol's desc)" viewIdResName:"myRect2" actions:[AX_FOCUS] bundle:[chromeRole="group", hint="Rectangle Symbol (From symbol's desc)"] +++++++View hint:"Rectangle Symbol (From symbol's desc)" viewIdResName:"myRect2" actions:[AX_FOCUS] bundle:[chromeRole="group", hint="Rectangle Symbol (From symbol's desc)"] \ No newline at end of file
diff --git a/content/test/data/accessibility/mac/attributes/ax-editable-ancestor-expected.txt b/content/test/data/accessibility/mac/attributes/ax-editable-ancestor-expected.txt new file mode 100644 index 0000000..11f326b9 --- /dev/null +++ b/content/test/data/accessibility/mac/attributes/ax-editable-ancestor-expected.txt
@@ -0,0 +1,8 @@ +editable.accessibilityAttributeValue(AXEditableAncestor)=:2 +editable.accessibilityAttributeNames.has(AXEditableAncestor)='yes' +not_applicable.accessibilityAttributeValue(AXEditableAncestor)=NULL +not_applicable.accessibilityAttributeNames.has(AXEditableAncestor)='no' +p.accessibilityAttributeValue(AXEditableAncestor)=:5 +p.accessibilityAttributeNames.has(AXEditableAncestor)='yes' +document.accessibilityAttributeNames.has(AXEditableAncestor)='no' +document.accessibilityAttributeValue(AXEditableAncestor)=NULL
diff --git a/content/test/data/accessibility/mac/attributes/ax-editable-ancestor.html b/content/test/data/accessibility/mac/attributes/ax-editable-ancestor.html new file mode 100644 index 0000000..cdac6181 --- /dev/null +++ b/content/test/data/accessibility/mac/attributes/ax-editable-ancestor.html
@@ -0,0 +1,19 @@ +<!-- +@SCRIPT: + editable.accessibilityAttributeValue(AXEditableAncestor) + editable.accessibilityAttributeNames.has(AXEditableAncestor) + not_applicable.accessibilityAttributeValue(AXEditableAncestor) + not_applicable.accessibilityAttributeNames.has(AXEditableAncestor) + p.accessibilityAttributeValue(AXEditableAncestor) + p.accessibilityAttributeNames.has(AXEditableAncestor) + document.accessibilityAttributeNames.has(AXEditableAncestor) + document.accessibilityAttributeValue(AXEditableAncestor) +--> +<!DOCTYPE html> +<textarea id="editable"></textarea> +<div id="not_applicable"></div> +<div contenteditable> + <div contenteditable> + <p id="p">Paragraph</p> + </div> +</div>
diff --git a/content/test/data/accessibility/mac/attributes/ax-highest-editable-ancestor-expected.txt b/content/test/data/accessibility/mac/attributes/ax-highest-editable-ancestor-expected.txt new file mode 100644 index 0000000..2b52a34 --- /dev/null +++ b/content/test/data/accessibility/mac/attributes/ax-highest-editable-ancestor-expected.txt
@@ -0,0 +1,8 @@ +editable.accessibilityAttributeValue(AXHighestEditableAncestor)=:2 +editable.accessibilityAttributeNames.has(AXHighestEditableAncestor)='yes' +not_applicable.accessibilityAttributeValue(AXHighestEditableAncestor)=NULL +not_applicable.accessibilityAttributeNames.has(AXHighestEditableAncestor)='no' +p.accessibilityAttributeValue(AXHighestEditableAncestor)=:4 +p.accessibilityAttributeNames.has(AXHighestEditableAncestor)='yes' +document.accessibilityAttributeNames.has(AXHighestEditableAncestor)='no' +document.accessibilityAttributeValue(AXHighestEditableAncestor)=NULL
diff --git a/content/test/data/accessibility/mac/attributes/ax-highest-editable-ancestor.html b/content/test/data/accessibility/mac/attributes/ax-highest-editable-ancestor.html new file mode 100644 index 0000000..efb014d --- /dev/null +++ b/content/test/data/accessibility/mac/attributes/ax-highest-editable-ancestor.html
@@ -0,0 +1,19 @@ +<!-- +@SCRIPT: + editable.accessibilityAttributeValue(AXHighestEditableAncestor) + editable.accessibilityAttributeNames.has(AXHighestEditableAncestor) + not_applicable.accessibilityAttributeValue(AXHighestEditableAncestor) + not_applicable.accessibilityAttributeNames.has(AXHighestEditableAncestor) + p.accessibilityAttributeValue(AXHighestEditableAncestor) + p.accessibilityAttributeNames.has(AXHighestEditableAncestor) + document.accessibilityAttributeNames.has(AXHighestEditableAncestor) + document.accessibilityAttributeValue(AXHighestEditableAncestor) +--> +<!DOCTYPE html> +<textarea id="editable"></textarea> +<div id="not_applicable"></div> +<div contenteditable> + <div contenteditable> + <p id="p">Paragraph</p> + <div> +</div>
diff --git a/content/test/data/accessibility/regression/remove-aria-owner-expected-auralinux.txt b/content/test/data/accessibility/regression/remove-aria-owner-expected-auralinux.txt new file mode 100644 index 0000000..e2ad8df7 --- /dev/null +++ b/content/test/data/accessibility/regression/remove-aria-owner-expected-auralinux.txt
@@ -0,0 +1,7 @@ +[document web] name='done' +++[section] +++++[section] +++++[section] +++++++[push button] name='1' +++[static] name='"' +++[static] name='"'
diff --git a/content/test/data/accessibility/regression/remove-aria-owner-expected-blink.txt b/content/test/data/accessibility/regression/remove-aria-owner-expected-blink.txt new file mode 100644 index 0000000..92c9b62 --- /dev/null +++ b/content/test/data/accessibility/regression/remove-aria-owner-expected-blink.txt
@@ -0,0 +1,18 @@ +rootWebArea name='done' +++genericContainer ignored +++++genericContainer ignored +++++++genericContainer +++++++++genericContainer +++++++++genericContainer +++++++++++button name='1' +++++++++++++staticText name='1' +++++++++++++++inlineTextBox name='1' +++++++genericContainer ignored +++++++++genericContainer ignored +++++++++++genericContainer ignored +++++++++++++staticText name='"' +++++++++++++++inlineTextBox name='"' +++++++++genericContainer ignored +++++++++++genericContainer ignored +++++++++++++staticText name='"' +++++++++++++++inlineTextBox name='"'
diff --git a/content/test/data/accessibility/regression/remove-aria-owner.html b/content/test/data/accessibility/regression/remove-aria-owner.html new file mode 100644 index 0000000..e17db8f --- /dev/null +++ b/content/test/data/accessibility/regression/remove-aria-owner.html
@@ -0,0 +1,35 @@ +<!-- +@WAIT-FOR:done +--> + +<div id="root"> + <div id="ownerParent"></div> + <div id="ownedLayer"> + <button id="btn1" role="button" aria-label="1" aria-disabled="false">1</button> + </div> +</div> + + +<q></q> +<style> +.no_quote q::before { content: no-close-quote; } +</style> +<script> + function addOwnerStep() { + let ownerElement = document.createElement('article'); + ownerElement.setAttribute("role", "region"); + ownerElement.setAttribute("aria-owns", "ownedLayer"); + ownerParent.appendChild(ownerElement); + setTimeout(removeOwnerStep, 100); + } + function removeOwnerStep() { + let ownerParent = document.getElementById("ownerParent"); + ownerParent.removeChild(ownerParent.firstChild); + setTimeout(() => { + document.title = 'done'; + }, 100) + } + window.addEventListener("load", () => { + setTimeout(addOwnerStep, 100); + }); +</script>
diff --git a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt index cfadaccf..66f3529 100644 --- a/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt +++ b/content/test/gpu/gpu_tests/test_expectations/webcodecs_expectations.txt
@@ -77,7 +77,6 @@ crbug.com/1208827 [ chromeos-board-amd64-generic ] WebCodecs_Encode_capture_avc1.42001E_prefer-hardware [ RetryOnFailure ] -crbug.com/1256493 [ chromeos-board-kevin ] WebCodecs_copyTo_hw_decoder [ Failure ] crbug.com/1207682 [ android ] WebCodecs_* [ RetryOnFailure ] crbug.com/1286918 [ android android-pixel-6 ] WebCodecs_TexImage2d_sw_decoder [ Failure ]
diff --git a/content/test/test_blink_web_unit_test_support.cc b/content/test/test_blink_web_unit_test_support.cc index 20ce04c..18e51ce 100644 --- a/content/test/test_blink_web_unit_test_support.cc +++ b/content/test/test_blink_web_unit_test_support.cc
@@ -179,6 +179,10 @@ return blink::WebString::FromUTF8("test_runner/0.0.0.0"); } +blink::WebString TestBlinkWebUnitTestSupport::FullUserAgent() { + return blink::WebString::FromUTF8("test_runner/0.0.0.0"); +} + blink::WebString TestBlinkWebUnitTestSupport::ReducedUserAgent() { return blink::WebString::FromUTF8("test_runner/0.0.0.0"); }
diff --git a/content/test/test_blink_web_unit_test_support.h b/content/test/test_blink_web_unit_test_support.h index f2a70ae..52fcdbad 100644 --- a/content/test/test_blink_web_unit_test_support.h +++ b/content/test/test_blink_web_unit_test_support.h
@@ -47,6 +47,7 @@ ~TestBlinkWebUnitTestSupport() override; blink::WebString UserAgent() override; + blink::WebString FullUserAgent() override; blink::WebString ReducedUserAgent() override; blink::WebString QueryLocalizedString(int resource_id) override; blink::WebString QueryLocalizedString(int resource_id,
diff --git a/docs/get_the_code.md b/docs/get_the_code.md index 06a6663..20b2a02 100644 --- a/docs/get_the_code.md +++ b/docs/get_the_code.md
@@ -1,19 +1,19 @@ -# Get the code: check out, build, and run Chromium. +# Get the code: check out, build, and run Chromium. + +[Browse or Search Chromium Code](https://source.chromium.org/chromium) online. Chromium supports building on Windows, Mac and Linux host systems. -Linux is required for building Android, and a Mac is required for building iOS. - The process for building Chrome is generally the same on all platforms, but each platform has a few quirks. In order to keep you from having to jump all over the place, we have a self-contained page for each configuration you might want to build: -* [Android](android_build_instructions.md) -* [Android Cast](android_cast_build_instructions.md) -* [Chrome OS](chromeos_build_instructions.md) +* [Android](android_build_instructions.md) (Build on Linux) +* [Android Cast](android_cast_build_instructions.md) (Build on Linux) +* [Chrome OS](chromeos_build_instructions.md) (Build on Linux) * [Fuchsia](fuchsia/build_instructions.md) -* [iOS](ios/build_instructions.md) +* [iOS](ios/build_instructions.md) (Build on Mac) * [Linux](linux/build_instructions.md) * [Linux Cast](linux/cast_build_instructions.md) * [Mac](mac_build_instructions.md)
diff --git a/extensions/browser/api/networking_private/networking_private_api.cc b/extensions/browser/api/networking_private/networking_private_api.cc index ca1dc6e..2593823f 100644 --- a/extensions/browser/api/networking_private/networking_private_api.cc +++ b/extensions/browser/api/networking_private/networking_private_api.cc
@@ -52,10 +52,11 @@ bool HasPrivateNetworkingAccess(const Extension* extension, Feature::Context context, - const GURL& source_url) { + const GURL& source_url, + int context_id) { return ExtensionAPI::GetSharedInstance() ->IsAvailable("networkingPrivate", extension, context, source_url, - CheckAliasStatus::NOT_ALLOWED) + CheckAliasStatus::NOT_ALLOWED, context_id) .is_available(); } @@ -71,8 +72,9 @@ PropertiesType type, const Extension* extension, Feature::Context context, - const GURL& source_url) { - if (HasPrivateNetworkingAccess(extension, context, source_url)) + const GURL& source_url, + int context_id) { + if (HasPrivateNetworkingAccess(extension, context, source_url, context_id)) return std::vector<std::string>(); const char* const* filter = nullptr; @@ -162,7 +164,7 @@ return; } FilterProperties(&result.value(), PropertiesType::GET, extension(), - source_context_type(), source_url()); + source_context_type(), source_url(), context_id()); Respond(OneArgument(std::move(*result))); } @@ -198,7 +200,7 @@ return; } FilterProperties(&result.value(), PropertiesType::GET, extension(), - source_context_type(), source_url()); + source_context_type(), source_url(), context_id()); Respond(OneArgument(std::move(*result))); } @@ -226,7 +228,7 @@ void NetworkingPrivateGetStateFunction::Success(base::Value result) { FilterProperties(&result, PropertiesType::GET, extension(), - source_context_type(), source_url()); + source_context_type(), source_url(), context_id()); Respond(OneArgument(std::move(result))); } @@ -251,7 +253,7 @@ std::vector<std::string> not_allowed_properties = FilterProperties(&properties_dict, PropertiesType::SET, extension(), - source_context_type(), source_url()); + source_context_type(), source_url(), context_id()); if (!not_allowed_properties.empty()) return RespondNow(Error(InvalidPropertiesError(not_allowed_properties))); @@ -299,7 +301,7 @@ std::vector<std::string> not_allowed_properties = FilterProperties(&properties_dict, PropertiesType::SET, extension(), - source_context_type(), source_url()); + source_context_type(), source_url(), context_id()); if (!not_allowed_properties.empty()) return RespondNow(Error(InvalidPropertiesError(not_allowed_properties))); @@ -416,7 +418,7 @@ // networkingPrivate permissions, i.e. apps that might have started using it // before its deprecation. if (!HasPrivateNetworkingAccess(extension(), source_context_type(), - source_url())) { + source_url(), context_id())) { return RespondNow(Error(kPrivateOnlyError)); } @@ -461,7 +463,7 @@ // networkingPrivate permissions, i.e. apps that might have started using it // before its deprecation. if (!HasPrivateNetworkingAccess(extension(), source_context_type(), - source_url())) { + source_url(), context_id())) { return RespondNow(Error(kPrivateOnlyError)); } @@ -644,7 +646,7 @@ ExtensionFunction::ResponseAction NetworkingPrivateStartActivateFunction::Run() { if (!HasPrivateNetworkingAccess(extension(), source_context_type(), - source_url())) { + source_url(), context_id())) { return RespondNow(Error(kPrivateOnlyError)); } @@ -719,7 +721,7 @@ ExtensionFunction::ResponseAction NetworkingPrivateUnlockCellularSimFunction::Run() { if (!HasPrivateNetworkingAccess(extension(), source_context_type(), - source_url())) { + source_url(), context_id())) { return RespondNow(Error(kPrivateOnlyError)); } @@ -758,7 +760,7 @@ ExtensionFunction::ResponseAction NetworkingPrivateSetCellularSimStateFunction::Run() { if (!HasPrivateNetworkingAccess(extension(), source_context_type(), - source_url())) { + source_url(), context_id())) { return RespondNow(Error(kPrivateOnlyError)); } @@ -799,7 +801,7 @@ ExtensionFunction::ResponseAction NetworkingPrivateSelectCellularMobileNetworkFunction::Run() { if (!HasPrivateNetworkingAccess(extension(), source_context_type(), - source_url())) { + source_url(), context_id())) { return RespondNow(Error(kPrivateOnlyError)); } @@ -858,7 +860,7 @@ ExtensionFunction::ResponseAction NetworkingPrivateGetCertificateListsFunction::Run() { if (!HasPrivateNetworkingAccess(extension(), source_context_type(), - source_url())) { + source_url(), context_id())) { return RespondNow(Error(kPrivateOnlyError)); }
diff --git a/extensions/browser/api_test_utils.cc b/extensions/browser/api_test_utils.cc index 886dbef..0758adf8 100644 --- a/extensions/browser/api_test_utils.cc +++ b/extensions/browser/api_test_utils.cc
@@ -140,7 +140,7 @@ !function->GetResultList()->GetListDeprecated().empty()) { const base::Value& single_result = function->GetResultList()->GetListDeprecated()[0]; - return single_result.CreateDeepCopy(); + return std::make_unique<base::Value>(single_result.Clone()); } return nullptr; }
diff --git a/extensions/browser/event_router.cc b/extensions/browser/event_router.cc index 3b6f27b..64c79466 100644 --- a/extensions/browser/event_router.cc +++ b/extensions/browser/event_router.cc
@@ -29,6 +29,7 @@ #include "extensions/browser/extension_host.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_system.h" +#include "extensions/browser/extension_util.h" #include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/process_manager.h" #include "extensions/browser/process_map.h" @@ -960,7 +961,8 @@ Feature::Availability availability = ExtensionAPI::GetSharedInstance()->IsAvailable( event->event_name, extension, target_context, listener_url, - CheckAliasStatus::ALLOWED); + CheckAliasStatus::ALLOWED, + util::GetBrowserContextId(browser_context_)); if (!availability.is_available()) { // It shouldn't be possible to reach here, because access is checked on // registration. However, for paranoia, check on dispatch as well.
diff --git a/extensions/browser/extension_function.cc b/extensions/browser/extension_function.cc index a9c8dc0..1023715 100644 --- a/extensions/browser/extension_function.cc +++ b/extensions/browser/extension_function.cc
@@ -37,6 +37,7 @@ #include "extensions/browser/extension_function_dispatcher.h" #include "extensions/browser/extension_function_registry.h" #include "extensions/browser/extension_registry.h" +#include "extensions/browser/extension_util.h" #include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/renderer_startup_helper.h" #include "extensions/common/constants.h" @@ -475,7 +476,7 @@ Feature::Availability availability = ExtensionAPI::GetSharedInstance()->IsAvailable( name_, extension_.get(), source_context_type_, source_url(), - extensions::CheckAliasStatus::ALLOWED); + extensions::CheckAliasStatus::ALLOWED, context_id_); return availability.is_available(); } @@ -586,6 +587,7 @@ return; } browser_context_ = dispatcher_->browser_context(); + context_id_ = extensions::util::GetBrowserContextId(browser_context_); shutdown_subscription_ = BrowserContextShutdownNotifierFactory::GetInstance() ->Get(browser_context_)
diff --git a/extensions/browser/extension_function.h b/extensions/browser/extension_function.h index 43ca2a78..18f351a 100644 --- a/extensions/browser/extension_function.h +++ b/extensions/browser/extension_function.h
@@ -240,6 +240,8 @@ virtual void SetName(const char* name); const char* name() const { return name_; } + int context_id() const { return context_id_; } + void set_profile_id(void* profile_id) { profile_id_ = profile_id; } void* profile_id() const { return profile_id_; } @@ -579,6 +581,9 @@ extensions::Feature::Context source_context_type_ = extensions::Feature::UNSPECIFIED_CONTEXT; + // The context ID of the browser context where this call originated. + int context_id_ = extensions::kUnspecifiedContextId; + // The process ID of the page that triggered this function call, or -1 // if unknown. int source_process_id_ = -1;
diff --git a/extensions/browser/renderer_startup_helper.cc b/extensions/browser/renderer_startup_helper.cc index 5a8c99b..e1aa243 100644 --- a/extensions/browser/renderer_startup_helper.cc +++ b/extensions/browser/renderer_startup_helper.cc
@@ -30,6 +30,7 @@ #include "extensions/common/extension_set.h" #include "extensions/common/extensions_client.h" #include "extensions/common/features/feature_channel.h" +#include "extensions/common/features/feature_developer_mode_only.h" #include "extensions/common/features/feature_session_type.h" #include "extensions/common/manifest_handlers/background_info.h" #include "extensions/common/permissions/permissions_data.h" @@ -132,6 +133,10 @@ if (activity_logging_enabled) renderer->SetActivityLoggingEnabled(activity_logging_enabled); + // extensions need to know the developer mode value for api restrictions. + renderer->SetDeveloperMode( + GetCurrentDeveloperMode(util::GetBrowserContextId(browser_context_))); + // Extensions need to know the channel and the session type for API // restrictions. The values are sent to all renderers, as the non-extension // renderers may have content scripts. @@ -315,6 +320,15 @@ extension_process_map_.erase(extension.id()); } +void RendererStartupHelper::OnDeveloperModeChanged(bool in_developer_mode) { + for (auto& process_entry : process_mojo_map_) { + content::RenderProcessHost* process = process_entry.first; + mojom::Renderer* renderer = GetRenderer(process); + if (renderer) + renderer->SetDeveloperMode(in_developer_mode); + } +} + void RendererStartupHelper::UnloadAllExtensionsForTest() { extension_process_map_.clear(); }
diff --git a/extensions/browser/renderer_startup_helper.h b/extensions/browser/renderer_startup_helper.h index 28953db9..3111098e 100644 --- a/extensions/browser/renderer_startup_helper.h +++ b/extensions/browser/renderer_startup_helper.h
@@ -72,6 +72,9 @@ void OnExtensionUnloaded(const Extension& extension); void OnExtensionLoaded(const Extension& extension); + // Sends a message to all renderers to update the developer mode. + void OnDeveloperModeChanged(bool in_developer_mode); + // Unload all extensions. Does not send notifications. void UnloadAllExtensionsForTest();
diff --git a/extensions/browser/renderer_startup_helper_unittest.cc b/extensions/browser/renderer_startup_helper_unittest.cc index 22225b3d7..d63d6d5 100644 --- a/extensions/browser/renderer_startup_helper_unittest.cc +++ b/extensions/browser/renderer_startup_helper_unittest.cc
@@ -103,6 +103,8 @@ void CancelSuspendExtension(const std::string& extension_id) override {} + void SetDeveloperMode(bool current_developer_mode) override {} + void SetSessionInfo(version_info::Channel channel, mojom::FeatureSessionType session, bool is_lock_screen_context) override {}
diff --git a/extensions/common/extension_api.cc b/extensions/common/extension_api.cc index 318ec9e0a..b53b7a9f 100644 --- a/extensions/common/extension_api.cc +++ b/extensions/common/extension_api.cc
@@ -164,17 +164,16 @@ dependency_providers_[name] = provider; } -bool ExtensionAPI::IsAnyFeatureAvailableToContext( - const Feature& api, - const Extension* extension, - Feature::Context context, - const GURL& url, - CheckAliasStatus check_alias) { +bool ExtensionAPI::IsAnyFeatureAvailableToContext(const Feature& api, + const Extension* extension, + Feature::Context context, + const GURL& url, + CheckAliasStatus check_alias, + int context_id) { auto provider = dependency_providers_.find("api"); CHECK(provider != dependency_providers_.end()); - // TODO(ghazale): We should pass a context ID into these methods. - if (api.IsAvailableToContext(extension, context, url, kUnspecifiedContextId) + if (api.IsAvailableToContext(extension, context, url, context_id) .is_available()) return true; @@ -183,10 +182,7 @@ const std::vector<const Feature*> features = provider->second->GetChildren(api); for (const Feature* feature : features) { - // TODO(ghazale): We should pass a context ID into these methods. - if (feature - ->IsAvailableToContext(extension, context, url, - kUnspecifiedContextId) + if (feature->IsAvailableToContext(extension, context, url, context_id) .is_available()) return true; } @@ -202,28 +198,29 @@ CHECK(alias) << "Cannot find alias feature " << alias_name << " for API feature " << api.name(); return IsAnyFeatureAvailableToContext(*alias, extension, context, url, - CheckAliasStatus::NOT_ALLOWED); + CheckAliasStatus::NOT_ALLOWED, + context_id); } Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name, const Extension* extension, Feature::Context context, const GURL& url, - CheckAliasStatus check_alias) { + CheckAliasStatus check_alias, + int context_id) { const Feature* feature = GetFeatureDependency(full_name); if (!feature) { return Feature::Availability(Feature::NOT_PRESENT, std::string("Unknown feature: ") + full_name); } - // TODO(ghazale): We should pass a context ID into these methods. - Feature::Availability availability = feature->IsAvailableToContext( - extension, context, url, kUnspecifiedContextId); + Feature::Availability availability = + feature->IsAvailableToContext(extension, context, url, context_id); if (availability.is_available() || check_alias != CheckAliasStatus::ALLOWED) return availability; - Feature::Availability alias_availability = - IsAliasAvailable(full_name, *feature, extension, context, url); + Feature::Availability alias_availability = IsAliasAvailable( + full_name, *feature, extension, context, url, context_id); return alias_availability.is_available() ? alias_availability : availability; } @@ -298,7 +295,8 @@ const Feature& feature, const Extension* extension, Feature::Context context, - const GURL& url) { + const GURL& url, + int context_id) { const std::string& alias = feature.alias(); if (alias.empty()) return Feature::Availability(Feature::NOT_PRESENT, "Alias not defined"); @@ -325,9 +323,8 @@ CHECK(alias_feature) << "Cannot find alias feature " << alias << " for API feature " << feature.name(); - // TODO(ghazale): We should pass a context ID into these methods. return alias_feature->IsAvailableToContext(extension, context, url, - kUnspecifiedContextId); + context_id); } base::StringPiece ExtensionAPI::GetSchemaStringPieceUnsafe(
diff --git a/extensions/common/extension_api.h b/extensions/common/extension_api.h index 938ed940..ee1fcd83 100644 --- a/extensions/common/extension_api.h +++ b/extensions/common/extension_api.h
@@ -111,7 +111,8 @@ const Extension* extension, Feature::Context context, const GURL& url, - CheckAliasStatus check_alias); + CheckAliasStatus check_alias, + int context_id); // Determines whether an API, or any parts of that API, can be exposed to // |context|. @@ -123,7 +124,8 @@ const Extension* extension, Feature::Context context, const GURL& url, - CheckAliasStatus check_alias); + CheckAliasStatus check_alias, + int context_id); // Gets the StringPiece for the schema specified by |api_name|. base::StringPiece GetSchemaStringPiece(const std::string& api_name); @@ -166,7 +168,8 @@ const Feature& feature, const Extension* extension, Feature::Context context, - const GURL& url); + const GURL& url, + int context_id); // Loads a schema. void LoadSchema(const std::string& name, const base::StringPiece& schema);
diff --git a/extensions/common/mojom/renderer.mojom b/extensions/common/mojom/renderer.mojom index d66c92b..ee97ec5c 100644 --- a/extensions/common/mojom/renderer.mojom +++ b/extensions/common/mojom/renderer.mojom
@@ -83,6 +83,9 @@ // Cancels suspending the extension. CancelSuspendExtension(string extension_id); + // Informs the renderer whether or not the developer mode is enabled. + SetDeveloperMode(bool developer_mode_only); + // Informs the renderer what channel (dev, beta, stable, etc) and user session // type is running. |is_lock_screen_context| represents whether the browser // context is associated with Chrome OS lock screen.
diff --git a/extensions/renderer/dispatcher.cc b/extensions/renderer/dispatcher.cc index 34b57743..4cec3648 100644 --- a/extensions/renderer/dispatcher.cc +++ b/extensions/renderer/dispatcher.cc
@@ -43,6 +43,7 @@ #include "extensions/common/features/behavior_feature.h" #include "extensions/common/features/feature.h" #include "extensions/common/features/feature_channel.h" +#include "extensions/common/features/feature_developer_mode_only.h" #include "extensions/common/features/feature_provider.h" #include "extensions/common/features/feature_session_type.h" #include "extensions/common/manifest_constants.h" @@ -129,11 +130,6 @@ namespace extensions { -// Constant to define the default profile id for the renderer to 0. -// Since each renderer is associated with a single context, we don't need -// separate ids for the profile. -const int kRendererProfileId = 0; - namespace { static const char kOnSuspendEvent[] = "runtime.onSuspend"; @@ -1345,6 +1341,10 @@ } } +void Dispatcher::SetDeveloperMode(bool current_developer_mode) { + SetCurrentDeveloperMode(kRendererProfileId, current_developer_mode); +} + void Dispatcher::SetSessionInfo(version_info::Channel channel, mojom::FeatureSessionType session_type, bool is_lock_screen_context) {
diff --git a/extensions/renderer/dispatcher.h b/extensions/renderer/dispatcher.h index c8dcb1f..e2cb976 100644 --- a/extensions/renderer/dispatcher.h +++ b/extensions/renderer/dispatcher.h
@@ -58,6 +58,12 @@ } // namespace content namespace extensions { + +// Constant to define the default profile id for the renderer to 0. +// Since each renderer is associated with a single context, we don't need +// separate ids for the profile. +const int kRendererProfileId = 0; + class ContentWatcher; class DispatcherDelegate; class Extension; @@ -231,6 +237,7 @@ const std::string& extension_id, mojom::Renderer::SuspendExtensionCallback callback) override; void CancelSuspendExtension(const std::string& extension_id) override; + void SetDeveloperMode(bool current_developer_mode) override; void SetSessionInfo(version_info::Channel channel, mojom::FeatureSessionType session_type, bool lock_screen_context) override;
diff --git a/extensions/renderer/feature_cache.cc b/extensions/renderer/feature_cache.cc index 744a6b6..695ab5bd 100644 --- a/extensions/renderer/feature_cache.cc +++ b/extensions/renderer/feature_cache.cc
@@ -11,6 +11,7 @@ #include "extensions/common/extension.h" #include "extensions/common/extension_api.h" #include "extensions/common/features/feature_provider.h" +#include "extensions/renderer/dispatcher.h" namespace extensions { @@ -31,8 +32,9 @@ DCHECK_NE(Feature::UNSPECIFIED_CONTEXT, context_type) << "FeatureCache shouldn't be used for unspecified contexts."; - const FeatureVector& features = GetFeaturesFromCache( - context_type, extension, url.DeprecatedGetOriginAsURL()); + const FeatureVector& features = + GetFeaturesFromCache(context_type, extension, + url.DeprecatedGetOriginAsURL(), kRendererProfileId); FeatureNameVector names; names.reserve(features.size()); for (const Feature* feature : features) { @@ -45,7 +47,7 @@ // change based on additional context attributes. if (ExtensionAPI::GetSharedInstance()->IsAnyFeatureAvailableToContext( *feature, extension, context_type, url, - CheckAliasStatus::NOT_ALLOWED)) { + CheckAliasStatus::NOT_ALLOWED, kRendererProfileId)) { names.push_back(feature->name()); } } @@ -64,14 +66,16 @@ const FeatureCache::FeatureVector& FeatureCache::GetFeaturesFromCache( Feature::Context context_type, const Extension* extension, - const GURL& origin) { + const GURL& origin, + int context_id) { if (context_type == Feature::WEBUI_CONTEXT || context_type == Feature::WEBUI_UNTRUSTED_CONTEXT) { auto iter = webui_cache_.find(origin); if (iter != webui_cache_.end()) return iter->second; return webui_cache_ - .emplace(origin, CreateCacheEntry(context_type, extension, origin)) + .emplace(origin, + CreateCacheEntry(context_type, extension, origin, context_id)) .first->second; } @@ -81,14 +85,16 @@ if (iter != extension_cache_.end()) return iter->second; return extension_cache_ - .emplace(key, CreateCacheEntry(context_type, extension, origin)) + .emplace(key, + CreateCacheEntry(context_type, extension, origin, context_id)) .first->second; } FeatureCache::FeatureVector FeatureCache::CreateCacheEntry( Feature::Context context_type, const Extension* extension, - const GURL& origin) { + const GURL& origin, + int context_id) { FeatureVector features; const FeatureProvider* api_feature_provider = FeatureProvider::GetAPIFeatures(); @@ -124,7 +130,7 @@ if (!ExtensionAPI::GetSharedInstance()->IsAnyFeatureAvailableToContext( *feature, extension, context_type, url_to_use, - CheckAliasStatus::NOT_ALLOWED)) { + CheckAliasStatus::NOT_ALLOWED, context_id)) { continue; }
diff --git a/extensions/renderer/feature_cache.h b/extensions/renderer/feature_cache.h index 57cd88b3..4392546 100644 --- a/extensions/renderer/feature_cache.h +++ b/extensions/renderer/feature_cache.h
@@ -61,13 +61,15 @@ // creating a new entry if one doesn't exist. const FeatureVector& GetFeaturesFromCache(Feature::Context context_type, const Extension* extension, - const GURL& origin); + const GURL& origin, + int context_id); // Creates a FeatureVector to be entered into a cache for the specified // context data. FeatureVector CreateCacheEntry(Feature::Context context_type, const Extension* extension, - const GURL& origin); + const GURL& origin, + int context_id); // The cache of extension-related contexts. These may be invalidated, since // extension permissions change.
diff --git a/extensions/renderer/script_context.cc b/extensions/renderer/script_context.cc index c4e4187..2418f3c9 100644 --- a/extensions/renderer/script_context.cc +++ b/extensions/renderer/script_context.cc
@@ -21,6 +21,7 @@ #include "extensions/common/extension_urls.h" #include "extensions/common/manifest_handlers/sandboxed_page_info.h" #include "extensions/common/permissions/permissions_data.h" +#include "extensions/renderer/dispatcher.h" #include "extensions/renderer/renderer_extension_registry.h" #include "extensions/renderer/v8_helpers.h" #include "third_party/blink/public/mojom/service_worker/service_worker_registration.mojom.h" @@ -337,7 +338,8 @@ extension = NULL; } return ExtensionAPI::GetSharedInstance()->IsAvailable( - api_name, extension, context_type_, url(), check_alias); + api_name, extension, context_type_, url(), check_alias, + kRendererProfileId); } std::string ScriptContext::GetContextTypeDescription() const { @@ -368,7 +370,7 @@ // web_frame() is null. GURL url = web_frame() ? GetDocumentLoaderURLForFrame(web_frame()) : url_; return ExtensionAPI::GetSharedInstance()->IsAnyFeatureAvailableToContext( - api, extension(), context_type(), url, check_alias); + api, extension(), context_type(), url, check_alias, kRendererProfileId); } // static
diff --git a/fuchsia/engine/renderer/web_engine_content_renderer_client.cc b/fuchsia/engine/renderer/web_engine_content_renderer_client.cc index 2520325c..6817eeb 100644 --- a/fuchsia/engine/renderer/web_engine_content_renderer_client.cc +++ b/fuchsia/engine/renderer/web_engine_content_renderer_client.cc
@@ -170,8 +170,9 @@ return std::make_unique<WebEngineURLLoaderThrottleProvider>(this); } -void WebEngineContentRendererClient::AddSupportedKeySystems( - std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) { +void WebEngineContentRendererClient::GetSupportedKeySystems( + media::GetSupportedKeySystemsCB cb) { + media::KeySystemPropertiesVector key_systems; media::SupportedCodecs supported_video_codecs = 0; constexpr uint8_t kUnknownCodecLevel = 0; if (IsSupportedHardwareVideoCodec(media::VideoType{ @@ -207,7 +208,7 @@ // video codecs. // TODO(crbug.com/1013412): Replace these hardcoded values with a query to // the fuchsia.mediacodec FIDL service. - key_systems->emplace_back(new cdm::WidevineKeySystemProperties( + key_systems.emplace_back(new cdm::WidevineKeySystemProperties( supported_codecs, // codecs encryption_schemes, // encryption schemes supported_codecs, // hw secure codecs @@ -225,9 +226,11 @@ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( switches::kPlayreadyKeySystem); if (!playready_key_system.empty()) { - key_systems->emplace_back(new PlayreadyKeySystemProperties( + key_systems.emplace_back(new PlayreadyKeySystemProperties( playready_key_system, supported_codecs)); } + + std::move(cb).Run(std::move(key_systems)); } bool WebEngineContentRendererClient::IsSupportedVideoType(
diff --git a/fuchsia/engine/renderer/web_engine_content_renderer_client.h b/fuchsia/engine/renderer/web_engine_content_renderer_client.h index 13f4b4f..6c755d4 100644 --- a/fuchsia/engine/renderer/web_engine_content_renderer_client.h +++ b/fuchsia/engine/renderer/web_engine_content_renderer_client.h
@@ -38,9 +38,7 @@ // content::ContentRendererClient overrides. void RenderThreadStarted() override; void RenderFrameCreated(content::RenderFrame* render_frame) override; - void AddSupportedKeySystems( - std::vector<std::unique_ptr<media::KeySystemProperties>>* key_systems) - override; + void GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb) override; bool IsSupportedVideoType(const media::VideoType& type) override; std::unique_ptr<blink::URLLoaderThrottleProvider> CreateURLLoaderThrottleProvider(
diff --git a/gpu/command_buffer/service/service_utils.cc b/gpu/command_buffer/service/service_utils.cc index 19c5470..d31e06a 100644 --- a/gpu/command_buffer/service/service_utils.cc +++ b/gpu/command_buffer/service/service_utils.cc
@@ -160,8 +160,7 @@ base::FeatureList::IsEnabled(features::kWebGPUService); gpu_preferences.enable_unsafe_webgpu = command_line->HasSwitch(switches::kEnableUnsafeWebGPU); - gpu_preferences.force_webgpu_compat = - command_line->HasSwitch(switches::kForceWebGPUCompat); + gpu_preferences.use_webgpu_adapter = ParseWebGPUAdapterName(command_line); if (command_line->HasSwitch(switches::kEnableDawnBackendValidation)) { auto value = command_line->GetSwitchValueASCII( switches::kEnableDawnBackendValidation); @@ -248,5 +247,25 @@ #endif } +WebGPUAdapterName ParseWebGPUAdapterName( + const base::CommandLine* command_line) { + if (command_line->HasSwitch(switches::kUseWebGPUAdapter)) { + auto value = command_line->GetSwitchValueASCII(switches::kUseWebGPUAdapter); + if (value.empty()) { + return WebGPUAdapterName::kDefault; + } else if (value == "compat") { + return WebGPUAdapterName::kCompat; + } else if (value == "swiftshader") { + return WebGPUAdapterName::kSwiftShader; + } else if (value == "default") { + return WebGPUAdapterName::kDefault; + } else { + DLOG(ERROR) << "Invalid switch " << switches::kUseWebGPUAdapter << "=" + << value << "."; + } + } + return WebGPUAdapterName::kDefault; +} + } // namespace gles2 } // namespace gpu
diff --git a/gpu/command_buffer/service/service_utils.h b/gpu/command_buffer/service/service_utils.h index e10ff73..408d7f81 100644 --- a/gpu/command_buffer/service/service_utils.h +++ b/gpu/command_buffer/service/service_utils.h
@@ -45,6 +45,9 @@ GPU_GLES2_EXPORT VulkanImplementationName ParseVulkanImplementationName(const base::CommandLine* command_line); +GPU_GLES2_EXPORT WebGPUAdapterName +ParseWebGPUAdapterName(const base::CommandLine* command_line); + } // namespace gles2 } // namespace gpu
diff --git a/gpu/command_buffer/service/shared_image_backing_raw_draw.cc b/gpu/command_buffer/service/shared_image_backing_raw_draw.cc index 37d9ea5..48b9300e 100644 --- a/gpu/command_buffer/service/shared_image_backing_raw_draw.cc +++ b/gpu/command_buffer/service/shared_image_backing_raw_draw.cc
@@ -230,7 +230,11 @@ paint_op_buffer_->Playback(surface->getCanvas(), playback_params); } - surface->flush(); + // Insert resolveMSAA in surface's command stream, so if the surface, + // otherwise gr_context->flush() call will not resolve to the wrapped + // backend_texture_. + surface->resolveMSAA(); + return true; }
diff --git a/gpu/command_buffer/service/shared_image_video_image_reader.cc b/gpu/command_buffer/service/shared_image_video_image_reader.cc index 3cabbcf4..5054bc5 100644 --- a/gpu/command_buffer/service/shared_image_video_image_reader.cc +++ b/gpu/command_buffer/service/shared_image_video_image_reader.cc
@@ -550,13 +550,16 @@ // being released and hence deadlock. // crbug.com/1262990 for more details. - DCHECK(release_fence.is_null()); if (gl_image_) { + DCHECK(release_fence.is_null()); if (scoped_hardware_buffer_) { scoped_hardware_buffer_->SetReadFence(gl_image_->TakeEndReadFence(), true); } gl_image_.reset(); + } else { + scoped_hardware_buffer_->SetReadFence(std::move(release_fence.owned_fd), + true); } scoped_hardware_buffer_.reset(); } @@ -575,6 +578,11 @@ return gl_image_.get(); } + AHardwareBuffer* GetAHardwareBuffer() override { + DCHECK(scoped_hardware_buffer_); + return scoped_hardware_buffer_->buffer(); + } + private: std::unique_ptr<base::android::ScopedHardwareBufferFenceSync> scoped_hardware_buffer_;
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc index c70ee3c..cfed99f0 100644 --- a/gpu/command_buffer/service/webgpu_decoder_impl.cc +++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
@@ -13,10 +13,13 @@ #include <memory> #include <vector> +#include "base/base_paths.h" #include "base/bits.h" +#include "base/files/file_path.h" #include "base/logging.h" #include "base/memory/raw_ptr.h" #include "base/numerics/checked_math.h" +#include "base/path_service.h" #include "base/trace_event/trace_event.h" #include "build/build_config.h" #include "components/viz/common/resources/resource_format_utils.h" @@ -44,6 +47,11 @@ #include "ui/gl/gl_angle_util_win.h" #endif +#if BUILDFLAG(IS_MAC) +#include "base/mac/bundle_locations.h" +#include "base/mac/foundation_util.h" +#endif + namespace gpu { namespace webgpu { @@ -469,7 +477,7 @@ std::vector<dawn::native::Adapter> dawn_adapters_; bool enable_unsafe_webgpu_ = false; - bool force_webgpu_compat_ = false; + WebGPUAdapterName use_webgpu_adapter_ = WebGPUAdapterName::kDefault; std::vector<std::string> force_enabled_toggles_; std::vector<std::string> force_disabled_toggles_; @@ -928,8 +936,38 @@ memory_tracker)), dawn_platform_(new DawnPlatform()), memory_transfer_service_(new DawnServiceMemoryTransferService(this)), - dawn_instance_(new dawn::native::Instance()), wire_serializer_(new WireServerCommandSerializer(client)) { + std::string dawn_search_path; + base::FilePath module_path; +#if BUILDFLAG(IS_MAC) + if (base::mac::AmIBundled()) { + dawn_search_path = base::mac::FrameworkBundlePath() + .Append("Libraries") + .AsEndingWithSeparator() + .MaybeAsASCII(); + } + if (dawn_search_path.empty()) +#endif + { + if (base::PathService::Get(base::DIR_MODULE, &module_path)) { + dawn_search_path = module_path.AsEndingWithSeparator().MaybeAsASCII(); + } + } + const char* dawn_search_path_c_str = dawn_search_path.c_str(); + + WGPUDawnInstanceDescriptor dawn_instance_desc = { + .chain = + { + .sType = WGPUSType_DawnInstanceDescriptor, + }, + .additionalRuntimeSearchPathsCount = dawn_search_path.empty() ? 0u : 1u, + .additionalRuntimeSearchPaths = &dawn_search_path_c_str, + }; + WGPUInstanceDescriptor instance_desc = { + .nextInChain = &dawn_instance_desc.chain, + }; + dawn_instance_ = std::make_unique<dawn::native::Instance>(&instance_desc); + dawn_instance_->SetPlatform(dawn_platform_.get()); switch (gpu_preferences.enable_dawn_backend_validation) { case DawnBackendValidationLevel::kDisabled: @@ -945,7 +983,7 @@ } enable_unsafe_webgpu_ = gpu_preferences.enable_unsafe_webgpu; - force_webgpu_compat_ = gpu_preferences.force_webgpu_compat; + use_webgpu_adapter_ = gpu_preferences.use_webgpu_adapter; force_enabled_toggles_ = gpu_preferences.enabled_dawn_features_list; force_disabled_toggles_ = gpu_preferences.disabled_dawn_features_list; @@ -970,7 +1008,7 @@ } ContextResult WebGPUDecoderImpl::Initialize() { - if (force_webgpu_compat_) { + if (use_webgpu_adapter_ == WebGPUAdapterName::kCompat) { gl_surface_ = new gl::SurfacelessEGL(gfx::Size(1, 1)); gl::GLContextAttribs attribs; attribs.client_major_es_version = 3; @@ -1166,7 +1204,7 @@ void WebGPUDecoderImpl::DiscoverAdapters() { #if BUILDFLAG(DAWN_ENABLE_BACKEND_OPENGLES) - if (force_webgpu_compat_) { + if (use_webgpu_adapter_ == WebGPUAdapterName::kCompat) { auto getProc = [](const char* pname) { return reinterpret_cast<void*>(eglGetProcAddress(pname)); }; @@ -1218,7 +1256,7 @@ continue; } - if (force_webgpu_compat_) { + if (use_webgpu_adapter_ == WebGPUAdapterName::kCompat) { if (adapterProperties.backendType == WGPUBackendType_OpenGLES) { dawn_adapters_.push_back(adapter); } @@ -1455,6 +1493,9 @@ PowerPreference power_preference = static_cast<PowerPreference>(c.power_preference); bool force_fallback_adapter = c.force_fallback_adapter; + if (use_webgpu_adapter_ == WebGPUAdapterName::kSwiftShader) { + force_fallback_adapter = true; + } if (gr_context_type_ != GrContextType::kVulkan) { #if BUILDFLAG(IS_LINUX)
diff --git a/gpu/config/gpu_finch_features.cc b/gpu/config/gpu_finch_features.cc index efef428..0214614 100644 --- a/gpu/config/gpu_finch_features.cc +++ b/gpu/config/gpu_finch_features.cc
@@ -349,10 +349,6 @@ if (IsUsingVulkan()) return false; - // Not yet compatible with SurfaceControl. - if (IsAndroidSurfaceControlEnabled()) - return false; - return base::FeatureList::IsEnabled(kWebViewThreadSafeMedia); #else return false; @@ -397,8 +393,9 @@ if (LimitAImageReaderMaxSizeToOne()) return false; - // On WebView we also require zero copy to use SurfaceControl - if (IsWebViewZeroCopyVideoEnabled() && + // On WebView we also require zero copy or thread-safe media to use + // SurfaceControl + if ((IsWebViewZeroCopyVideoEnabled() || IsUsingThreadSafeMediaForWebView()) && base::FeatureList::IsEnabled(kWebViewSurfaceControl)) return true;
diff --git a/gpu/config/gpu_info_collector.cc b/gpu/config/gpu_info_collector.cc index 9bc6b72..f36a629 100644 --- a/gpu/config/gpu_info_collector.cc +++ b/gpu/config/gpu_info_collector.cc
@@ -11,10 +11,13 @@ #include <utility> #include <vector> +#include "base/base_paths.h" #include "base/command_line.h" #include "base/cxx17_backports.h" +#include "base/files/file_path.h" #include "base/logging.h" #include "base/metrics/histogram_functions.h" +#include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/string_split.h" @@ -37,6 +40,11 @@ #include "ui/gl/init/create_gr_gl_interface.h" #include "ui/gl/init/gl_factory.h" +#if BUILDFLAG(IS_MAC) +#include "base/mac/bundle_locations.h" +#include "base/mac/foundation_util.h" +#endif + #if defined(USE_OZONE) #include "ui/ozone/public/ozone_platform.h" // nogncheck #include "ui/ozone/public/platform_gl_egl_utility.h" // nogncheck @@ -607,7 +615,34 @@ DawnProcTable procs = dawn::native::GetProcs(); dawnProcSetProcs(&procs); - auto instance = std::make_unique<dawn::native::Instance>(); + std::string dawn_search_path; + base::FilePath module_path; +#if BUILDFLAG(IS_MAC) + if (base::mac::AmIBundled()) { + dawn_search_path = base::mac::FrameworkBundlePath() + .Append("Libraries") + .AsEndingWithSeparator() + .MaybeAsASCII(); + } + if (dawn_search_path.empty()) +#endif + { + if (base::PathService::Get(base::DIR_MODULE, &module_path)) { + dawn_search_path = module_path.AsEndingWithSeparator().MaybeAsASCII(); + } + } + const char* dawn_search_path_c_str = dawn_search_path.c_str(); + + wgpu::DawnInstanceDescriptor dawn_instance_desc = {}; + dawn_instance_desc.additionalRuntimeSearchPathsCount = + dawn_search_path.empty() ? 0u : 1u; + dawn_instance_desc.additionalRuntimeSearchPaths = &dawn_search_path_c_str; + + wgpu::InstanceDescriptor instance_desc = {}; + instance_desc.nextInChain = &dawn_instance_desc; + + auto instance = std::make_unique<dawn::native::Instance>( + reinterpret_cast<const WGPUInstanceDescriptor*>(&instance_desc)); instance->DiscoverDefaultAdapters(); std::vector<dawn::native::Adapter> adapters = instance->GetAdapters();
diff --git a/gpu/config/gpu_preferences.h b/gpu/config/gpu_preferences.h index 5008130..17f2c70 100644 --- a/gpu/config/gpu_preferences.h +++ b/gpu/config/gpu_preferences.h
@@ -37,6 +37,12 @@ kLast = kSwiftshader, }; +enum class WebGPUAdapterName : uint32_t { + kDefault = 0, + kCompat = 1, + kSwiftShader = 2, +}; + enum class GrContextType : uint32_t { kGL = 0, kVulkan = 1, @@ -249,8 +255,8 @@ DawnBackendValidationLevel enable_dawn_backend_validation = DawnBackendValidationLevel::kDisabled; - // Force the use of the WebGPU/Compat (GLES) backend for all WebGPU content. - bool force_webgpu_compat = false; + // The adapter to use for WebGPU content. + WebGPUAdapterName use_webgpu_adapter = WebGPUAdapterName::kDefault; // The Dawn features(toggles) enabled on the creation of Dawn devices. std::vector<std::string> enabled_dawn_features_list;
diff --git a/gpu/config/gpu_switches.cc b/gpu/config/gpu_switches.cc index 15fe6b4..17d91d4 100644 --- a/gpu/config/gpu_switches.cc +++ b/gpu/config/gpu_switches.cc
@@ -46,8 +46,8 @@ // Enable validation layers in Dawn backends. const char kEnableDawnBackendValidation[] = "enable-dawn-backend-validation"; -// Force all WebGPU content to run on the WebGPU/Compat (GLES) backend. -const char kForceWebGPUCompat[] = "force-webgpu-compat"; +// The adapter to use for WebGPU content. +GPU_EXPORT extern const char kUseWebGPUAdapter[] = "use-webgpu-adapter"; // Set the Dawn features(toggles) enabled on the creation of Dawn devices. const char kEnableDawnFeatures[] = "enable-dawn-features";
diff --git a/gpu/config/gpu_switches.h b/gpu/config/gpu_switches.h index 28ebe16..f4d43cd 100644 --- a/gpu/config/gpu_switches.h +++ b/gpu/config/gpu_switches.h
@@ -20,7 +20,7 @@ GPU_EXPORT extern const char kDisableGpuProcessForDX12InfoCollection[]; GPU_EXPORT extern const char kEnableUnsafeWebGPU[]; GPU_EXPORT extern const char kEnableDawnBackendValidation[]; -GPU_EXPORT extern const char kForceWebGPUCompat[]; +GPU_EXPORT extern const char kUseWebGPUAdapter[]; GPU_EXPORT extern const char kEnableDawnFeatures[]; GPU_EXPORT extern const char kDisableDawnFeatures[]; GPU_EXPORT extern const char kUseHighGPUThreadPriorityForPerfTests[];
diff --git a/gpu/ipc/common/gpu_preferences.mojom b/gpu/ipc/common/gpu_preferences.mojom index b62525b..fd28170ea 100644 --- a/gpu/ipc/common/gpu_preferences.mojom +++ b/gpu/ipc/common/gpu_preferences.mojom
@@ -19,6 +19,13 @@ kLast = kSwiftshader, }; +// Corresponds to gpu::WebGPUAdapterName. +enum WebGPUAdapterName { + kDefault = 0, + kCompat = 1, + kSwiftShader = 2, +}; + // Corresponds to gpu::GrContextType. enum GrContextType { kGL = 0, @@ -90,7 +97,7 @@ bool enable_gpu_benchmarking_extension; bool enable_webgpu; bool enable_unsafe_webgpu; - bool force_webgpu_compat; + WebGPUAdapterName use_webgpu_adapter; DawnBackendValidationLevel enable_dawn_backend_validation; array<string> enabled_dawn_features_list; array<string> disabled_dawn_features_list;
diff --git a/gpu/ipc/common/gpu_preferences_mojom_traits.h b/gpu/ipc/common/gpu_preferences_mojom_traits.h index 1759c05f..7480cd6 100644 --- a/gpu/ipc/common/gpu_preferences_mojom_traits.h +++ b/gpu/ipc/common/gpu_preferences_mojom_traits.h
@@ -96,6 +96,38 @@ }; template <> +struct GPU_EXPORT + EnumTraits<gpu::mojom::WebGPUAdapterName, gpu::WebGPUAdapterName> { + static gpu::mojom::WebGPUAdapterName ToMojom(gpu::WebGPUAdapterName input) { + switch (input) { + case gpu::WebGPUAdapterName::kDefault: + return gpu::mojom::WebGPUAdapterName::kDefault; + case gpu::WebGPUAdapterName::kCompat: + return gpu::mojom::WebGPUAdapterName::kCompat; + case gpu::WebGPUAdapterName::kSwiftShader: + return gpu::mojom::WebGPUAdapterName::kSwiftShader; + } + NOTREACHED(); + return gpu::mojom::WebGPUAdapterName::kDefault; + } + static bool FromMojom(gpu::mojom::WebGPUAdapterName input, + gpu::WebGPUAdapterName* out) { + switch (input) { + case gpu::mojom::WebGPUAdapterName::kDefault: + *out = gpu::WebGPUAdapterName::kDefault; + return true; + case gpu::mojom::WebGPUAdapterName::kCompat: + *out = gpu::WebGPUAdapterName::kCompat; + return true; + case gpu::mojom::WebGPUAdapterName::kSwiftShader: + *out = gpu::WebGPUAdapterName::kSwiftShader; + return true; + } + return false; + } +}; + +template <> struct GPU_EXPORT EnumTraits<gpu::mojom::DawnBackendValidationLevel, gpu::DawnBackendValidationLevel> { static gpu::mojom::DawnBackendValidationLevel ToMojom( @@ -207,7 +239,8 @@ prefs.enable_gpu_benchmarking_extension(); out->enable_webgpu = prefs.enable_webgpu(); out->enable_unsafe_webgpu = prefs.enable_unsafe_webgpu(); - out->force_webgpu_compat = prefs.force_webgpu_compat(); + if (!prefs.ReadUseWebgpuAdapter(&out->use_webgpu_adapter)) + return false; if (!prefs.ReadEnableDawnBackendValidation( &out->enable_dawn_backend_validation)) return false; @@ -393,8 +426,9 @@ static bool enable_unsafe_webgpu(const gpu::GpuPreferences& prefs) { return prefs.enable_unsafe_webgpu; } - static bool force_webgpu_compat(const gpu::GpuPreferences& prefs) { - return prefs.force_webgpu_compat; + static gpu::WebGPUAdapterName use_webgpu_adapter( + const gpu::GpuPreferences& prefs) { + return prefs.use_webgpu_adapter; } static gpu::DawnBackendValidationLevel enable_dawn_backend_validation( const gpu::GpuPreferences& prefs) {
diff --git a/infra/config/generated/builders/ci/ToTiOS/properties.textpb b/infra/config/generated/builders/ci/ToTiOS/properties.textpb index ce5e12f..13d9a2f 100644 --- a/infra/config/generated/builders/ci/ToTiOS/properties.textpb +++ b/infra/config/generated/builders/ci/ToTiOS/properties.textpb
@@ -12,5 +12,5 @@ "sheriff_rotations": [ "chromium.clang" ], - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ToTiOSDevice/properties.textpb b/infra/config/generated/builders/ci/ToTiOSDevice/properties.textpb index ce5e12f..13d9a2f 100644 --- a/infra/config/generated/builders/ci/ToTiOSDevice/properties.textpb +++ b/infra/config/generated/builders/ci/ToTiOSDevice/properties.textpb
@@ -12,5 +12,5 @@ "sheriff_rotations": [ "chromium.clang" ], - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios-asan/properties.textpb b/infra/config/generated/builders/ci/ios-asan/properties.textpb index 9015f79..c18caf9e 100644 --- a/infra/config/generated/builders/ci/ios-asan/properties.textpb +++ b/infra/config/generated/builders/ci/ios-asan/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "chromium.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios-device/properties.textpb b/infra/config/generated/builders/ci/ios-device/properties.textpb index 6d2a595..b65703ff 100644 --- a/infra/config/generated/builders/ci/ios-device/properties.textpb +++ b/infra/config/generated/builders/ci/ios-device/properties.textpb
@@ -17,5 +17,5 @@ "chromium", "ios" ], - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios-reclient/properties.textpb b/infra/config/generated/builders/ci/ios-reclient/properties.textpb index cfa802e..3a80cd1 100644 --- a/infra/config/generated/builders/ci/ios-reclient/properties.textpb +++ b/infra/config/generated/builders/ci/ios-reclient/properties.textpb
@@ -17,5 +17,5 @@ }, "builder_group": "chromium.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios-simulator-code-coverage/properties.textpb b/infra/config/generated/builders/ci/ios-simulator-code-coverage/properties.textpb index c719ff8..ffb8a12 100644 --- a/infra/config/generated/builders/ci/ios-simulator-code-coverage/properties.textpb +++ b/infra/config/generated/builders/ci/ios-simulator-code-coverage/properties.textpb
@@ -21,5 +21,5 @@ }, "builder_group": "chromium.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios-simulator-cronet/properties.textpb b/infra/config/generated/builders/ci/ios-simulator-cronet/properties.textpb index 9015f79..c18caf9e 100644 --- a/infra/config/generated/builders/ci/ios-simulator-cronet/properties.textpb +++ b/infra/config/generated/builders/ci/ios-simulator-cronet/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "chromium.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios-simulator-full-configs/properties.textpb b/infra/config/generated/builders/ci/ios-simulator-full-configs/properties.textpb index 6d2a595..b65703ff 100644 --- a/infra/config/generated/builders/ci/ios-simulator-full-configs/properties.textpb +++ b/infra/config/generated/builders/ci/ios-simulator-full-configs/properties.textpb
@@ -17,5 +17,5 @@ "chromium", "ios" ], - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios-simulator-multi-window/properties.textpb b/infra/config/generated/builders/ci/ios-simulator-multi-window/properties.textpb index 9015f79..c18caf9e 100644 --- a/infra/config/generated/builders/ci/ios-simulator-multi-window/properties.textpb +++ b/infra/config/generated/builders/ci/ios-simulator-multi-window/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "chromium.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios-simulator-noncq/properties.textpb b/infra/config/generated/builders/ci/ios-simulator-noncq/properties.textpb index 6d2a595..b65703ff 100644 --- a/infra/config/generated/builders/ci/ios-simulator-noncq/properties.textpb +++ b/infra/config/generated/builders/ci/ios-simulator-noncq/properties.textpb
@@ -17,5 +17,5 @@ "chromium", "ios" ], - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios-simulator/properties.textpb b/infra/config/generated/builders/ci/ios-simulator/properties.textpb index 6d2a595..b65703ff 100644 --- a/infra/config/generated/builders/ci/ios-simulator/properties.textpb +++ b/infra/config/generated/builders/ci/ios-simulator/properties.textpb
@@ -17,5 +17,5 @@ "chromium", "ios" ], - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios14-beta-simulator/properties.textpb b/infra/config/generated/builders/ci/ios14-beta-simulator/properties.textpb index 9015f79..c18caf9e 100644 --- a/infra/config/generated/builders/ci/ios14-beta-simulator/properties.textpb +++ b/infra/config/generated/builders/ci/ios14-beta-simulator/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "chromium.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios14-sdk-simulator/properties.textpb b/infra/config/generated/builders/ci/ios14-sdk-simulator/properties.textpb index 9015f79..c18caf9e 100644 --- a/infra/config/generated/builders/ci/ios14-sdk-simulator/properties.textpb +++ b/infra/config/generated/builders/ci/ios14-sdk-simulator/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "chromium.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/ci/ios15-beta-simulator/properties.textpb b/infra/config/generated/builders/ci/ios15-beta-simulator/properties.textpb index 9015f79..c18caf9e 100644 --- a/infra/config/generated/builders/ci/ios15-beta-simulator/properties.textpb +++ b/infra/config/generated/builders/ci/ios15-beta-simulator/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "chromium.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/goma/Chromium iOS Goma RBE ToT/properties.textpb b/infra/config/generated/builders/goma/Chromium iOS Goma RBE ToT/properties.textpb index 81bd186..9941edb 100644 --- a/infra/config/generated/builders/goma/Chromium iOS Goma RBE ToT/properties.textpb +++ b/infra/config/generated/builders/goma/Chromium iOS Goma RBE ToT/properties.textpb
@@ -14,5 +14,5 @@ }, "builder_group": "chromium.goma", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/properties.textpb b/infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/properties.textpb index 378804f5..8aeb7c4e 100644 --- a/infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/properties.textpb +++ b/infra/config/generated/builders/goma/ios-device-goma-rbe-canary-clobber/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "chromium.goma.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/goma/ios-device-goma-rbe-latest-clobber/properties.textpb b/infra/config/generated/builders/goma/ios-device-goma-rbe-latest-clobber/properties.textpb index 378804f5..8aeb7c4e 100644 --- a/infra/config/generated/builders/goma/ios-device-goma-rbe-latest-clobber/properties.textpb +++ b/infra/config/generated/builders/goma/ios-device-goma-rbe-latest-clobber/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "chromium.goma.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios-device/properties.textpb b/infra/config/generated/builders/try/ios-device/properties.textpb index d729138..b9041d6 100644 --- a/infra/config/generated/builders/try/ios-device/properties.textpb +++ b/infra/config/generated/builders/try/ios-device/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "tryserver.chromium.mac", "recipe": "chromium_trybot", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios-simulator-cronet/properties.textpb b/infra/config/generated/builders/try/ios-simulator-cronet/properties.textpb index b4f1b39f..331d60c9 100644 --- a/infra/config/generated/builders/try/ios-simulator-cronet/properties.textpb +++ b/infra/config/generated/builders/try/ios-simulator-cronet/properties.textpb
@@ -16,5 +16,5 @@ }, "builder_group": "tryserver.chromium.mac", "recipe": "chromium_trybot", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios-simulator-full-configs/properties.textpb b/infra/config/generated/builders/try/ios-simulator-full-configs/properties.textpb index b3b23b3..8ddd327 100644 --- a/infra/config/generated/builders/try/ios-simulator-full-configs/properties.textpb +++ b/infra/config/generated/builders/try/ios-simulator-full-configs/properties.textpb
@@ -24,5 +24,5 @@ }, "builder_group": "tryserver.chromium.mac", "recipe": "chromium_trybot", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios-simulator-inverse-fieldtrials-fyi/properties.textpb b/infra/config/generated/builders/try/ios-simulator-inverse-fieldtrials-fyi/properties.textpb index d729138..b9041d6 100644 --- a/infra/config/generated/builders/try/ios-simulator-inverse-fieldtrials-fyi/properties.textpb +++ b/infra/config/generated/builders/try/ios-simulator-inverse-fieldtrials-fyi/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "tryserver.chromium.mac", "recipe": "chromium_trybot", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios-simulator-multi-window/properties.textpb b/infra/config/generated/builders/try/ios-simulator-multi-window/properties.textpb index d729138..b9041d6 100644 --- a/infra/config/generated/builders/try/ios-simulator-multi-window/properties.textpb +++ b/infra/config/generated/builders/try/ios-simulator-multi-window/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "tryserver.chromium.mac", "recipe": "chromium_trybot", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios-simulator-noncq/properties.textpb b/infra/config/generated/builders/try/ios-simulator-noncq/properties.textpb index d729138..b9041d6 100644 --- a/infra/config/generated/builders/try/ios-simulator-noncq/properties.textpb +++ b/infra/config/generated/builders/try/ios-simulator-noncq/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "tryserver.chromium.mac", "recipe": "chromium_trybot", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios-simulator-rts/properties.textpb b/infra/config/generated/builders/try/ios-simulator-rts/properties.textpb index f76468b5..615f95e6 100644 --- a/infra/config/generated/builders/try/ios-simulator-rts/properties.textpb +++ b/infra/config/generated/builders/try/ios-simulator-rts/properties.textpb
@@ -20,5 +20,5 @@ }, "builder_group": "tryserver.chromium.mac", "recipe": "chromium_trybot", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios-simulator/properties.textpb b/infra/config/generated/builders/try/ios-simulator/properties.textpb index b3b23b3..8ddd327 100644 --- a/infra/config/generated/builders/try/ios-simulator/properties.textpb +++ b/infra/config/generated/builders/try/ios-simulator/properties.textpb
@@ -24,5 +24,5 @@ }, "builder_group": "tryserver.chromium.mac", "recipe": "chromium_trybot", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios14-beta-simulator/properties.textpb b/infra/config/generated/builders/try/ios14-beta-simulator/properties.textpb index d729138..b9041d6 100644 --- a/infra/config/generated/builders/try/ios14-beta-simulator/properties.textpb +++ b/infra/config/generated/builders/try/ios14-beta-simulator/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "tryserver.chromium.mac", "recipe": "chromium_trybot", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios14-sdk-simulator/properties.textpb b/infra/config/generated/builders/try/ios14-sdk-simulator/properties.textpb index d729138..b9041d6 100644 --- a/infra/config/generated/builders/try/ios14-sdk-simulator/properties.textpb +++ b/infra/config/generated/builders/try/ios14-sdk-simulator/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "tryserver.chromium.mac", "recipe": "chromium_trybot", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/try/ios15-beta-simulator/properties.textpb b/infra/config/generated/builders/try/ios15-beta-simulator/properties.textpb index d729138..b9041d6 100644 --- a/infra/config/generated/builders/try/ios15-beta-simulator/properties.textpb +++ b/infra/config/generated/builders/try/ios15-beta-simulator/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "tryserver.chromium.mac", "recipe": "chromium_trybot", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI ios-device/properties.textpb b/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI ios-device/properties.textpb index 20f89474..4a1ddcf 100644 --- a/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI ios-device/properties.textpb +++ b/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI ios-device/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "chromium.webrtc.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI ios-simulator/properties.textpb b/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI ios-simulator/properties.textpb index 20f89474..4a1ddcf 100644 --- a/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI ios-simulator/properties.textpb +++ b/infra/config/generated/builders/webrtc.fyi/WebRTC Chromium FYI ios-simulator/properties.textpb
@@ -13,5 +13,5 @@ }, "builder_group": "chromium.webrtc.fyi", "recipe": "chromium", - "xcode_build_version": "13a233" + "xcode_build_version": "13c100" } \ No newline at end of file
diff --git a/infra/config/generated/luci/cr-buildbucket.cfg b/infra/config/generated/luci/cr-buildbucket.cfg index e44fb64..6a3cf98 100644 --- a/infra/config/generated/luci/cr-buildbucket.cfg +++ b/infra/config/generated/luci/cr-buildbucket.cfg
@@ -9000,12 +9000,12 @@ ' },' ' "builder_group": "chromium.fuzz",' ' "recipe": "chromium_libfuzzer",' - ' "xcode_build_version": "13a233"' + ' "xcode_build_version": "13c100"' '}' execution_timeout_secs: 14400 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -18477,8 +18477,8 @@ '}' execution_timeout_secs: 50400 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -18562,8 +18562,8 @@ '}' execution_timeout_secs: 50400 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -28926,12 +28926,12 @@ ' "builder_group": "chromium.angle",' ' "perf_dashboard_machine_group": "ChromiumANGLE",' ' "recipe": "angle_chromium",' - ' "xcode_build_version": "13a233"' + ' "xcode_build_version": "13c100"' '}' execution_timeout_secs: 10800 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-gpu-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -29078,8 +29078,8 @@ '}' execution_timeout_secs: 36000 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -29248,8 +29248,8 @@ '}' execution_timeout_secs: 10800 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -29329,8 +29329,8 @@ '}' execution_timeout_secs: 36000 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -29415,8 +29415,8 @@ '}' execution_timeout_secs: 10800 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -29497,8 +29497,8 @@ '}' execution_timeout_secs: 72000 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -29578,8 +29578,8 @@ '}' execution_timeout_secs: 36000 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -29663,8 +29663,8 @@ '}' execution_timeout_secs: 10800 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -29744,8 +29744,8 @@ '}' execution_timeout_secs: 36000 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -29829,8 +29829,8 @@ '}' execution_timeout_secs: 10800 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -29991,8 +29991,8 @@ '}' execution_timeout_secs: 36000 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -30072,8 +30072,8 @@ '}' execution_timeout_secs: 36000 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -30153,8 +30153,8 @@ '}' execution_timeout_secs: 36000 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -43621,8 +43621,8 @@ '}' execution_timeout_secs: 10800 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com" @@ -44758,8 +44758,8 @@ '}' execution_timeout_secs: 36000 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com" @@ -44810,8 +44810,8 @@ '}' execution_timeout_secs: 36000 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "goma-release-testing@chops-service-accounts.iam.gserviceaccount.com" @@ -60053,8 +60053,8 @@ path: "win_toolchain" } caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -60145,8 +60145,8 @@ path: "win_toolchain" } caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -60237,8 +60237,8 @@ path: "win_toolchain" } caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -60329,8 +60329,8 @@ path: "win_toolchain" } caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -60421,8 +60421,8 @@ path: "win_toolchain" } caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -60513,8 +60513,8 @@ path: "win_toolchain" } caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -60605,8 +60605,8 @@ path: "win_toolchain" } caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -60697,8 +60697,8 @@ path: "win_toolchain" } caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -60789,8 +60789,8 @@ path: "win_toolchain" } caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -60881,8 +60881,8 @@ path: "win_toolchain" } caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -60973,8 +60973,8 @@ path: "win_toolchain" } caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-try-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -77418,8 +77418,8 @@ '}' execution_timeout_secs: 7200 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com" @@ -77469,8 +77469,8 @@ '}' execution_timeout_secs: 7200 caches { - name: "xcode_ios_13a233" - path: "xcode_ios_13a233.app" + name: "xcode_ios_13c100" + path: "xcode_ios_13c100.app" } build_numbers: YES service_account: "chromium-ci-builder@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/infra/config/lib/builders.star b/infra/config/lib/builders.star index 6ab1e54e..c4d2036 100644 --- a/infra/config/lib/builders.star +++ b/infra/config/lib/builders.star
@@ -186,7 +186,7 @@ # Xcode 12.5. Requires Mac11+ OS. x12e262 = xcode_enum("12e262"), # Default Xcode 13 for chromium iOS. - x13main = xcode_enum("13a233"), + x13main = xcode_enum("13c100"), # A newer Xcode version used on beta bots. x13betabots = xcode_enum("13c100"), # in use by ios-webkit-tot
diff --git a/ios/chrome/app/BUILD.gn b/ios/chrome/app/BUILD.gn index e1f2c881..d221d1c 100644 --- a/ios/chrome/app/BUILD.gn +++ b/ios/chrome/app/BUILD.gn
@@ -137,21 +137,6 @@ } } -source_set("content_suggestions_scheduler_app_state_agent") { - configs += [ "//build/config/compiler:enable_arc" ] - sources = [ - "content_suggestions_scheduler_app_state_agent.h", - "content_suggestions_scheduler_app_state_agent.mm", - ] - deps = [ - "//components/ntp_snippets", - "//components/previous_session_info", - "//ios/chrome/app/application_delegate:observing_app_state_agent", - "//ios/chrome/browser/metrics", - "//ios/chrome/browser/ntp_snippets", - ] -} - if (ios_enable_credential_provider_extension) { source_set("credential_provider_migrator_app_agent") { configs += [ "//build/config/compiler:enable_arc" ] @@ -287,7 +272,6 @@ ":app", ":app_metrics_app_state_agent", ":blocking_scene_commands", - ":content_suggestions_scheduler_app_state_agent", ":enterprise_app_agent", ":first_run_app_state_agent", ":mode",
diff --git a/ios/chrome/app/DEPS b/ios/chrome/app/DEPS index 860c1bc..4136179 100644 --- a/ios/chrome/app/DEPS +++ b/ios/chrome/app/DEPS
@@ -15,7 +15,6 @@ "+components/history/core/browser", "+components/keyed_service/core", "+components/metrics", - "+components/ntp_snippets", "+components/password_manager/core/common", "+components/payments/core", "+components/policy/core/common",
diff --git a/ios/chrome/app/application_delegate/BUILD.gn b/ios/chrome/app/application_delegate/BUILD.gn index de46c7c7..5870766 100644 --- a/ios/chrome/app/application_delegate/BUILD.gn +++ b/ios/chrome/app/application_delegate/BUILD.gn
@@ -220,7 +220,6 @@ "//ios/chrome/browser/main:public", "//ios/chrome/browser/metrics", "//ios/chrome/browser/metrics:metrics_internal", - "//ios/chrome/browser/ntp_snippets:ntp_snippets", "//ios/chrome/browser/policy:policy_util", "//ios/chrome/browser/search_engines", "//ios/chrome/browser/signin",
diff --git a/ios/chrome/app/content_suggestions_scheduler_app_state_agent.h b/ios/chrome/app/content_suggestions_scheduler_app_state_agent.h deleted file mode 100644 index 285eb66..0000000 --- a/ios/chrome/app/content_suggestions_scheduler_app_state_agent.h +++ /dev/null
@@ -1,15 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef IOS_CHROME_APP_CONTENT_SUGGESTIONS_SCHEDULER_APP_STATE_AGENT_H_ -#define IOS_CHROME_APP_CONTENT_SUGGESTIONS_SCHEDULER_APP_STATE_AGENT_H_ - -#import "ios/chrome/app/application_delegate/observing_app_state_agent.h" - -// The agent that notifies the content suggestions service about app lifecycle -// events to keep the model up to date. -@interface ContentSuggestionsSchedulerAppAgent : SceneObservingAppAgent -@end - -#endif // IOS_CHROME_APP_CONTENT_SUGGESTIONS_SCHEDULER_APP_STATE_AGENT_H_
diff --git a/ios/chrome/app/content_suggestions_scheduler_app_state_agent.mm b/ios/chrome/app/content_suggestions_scheduler_app_state_agent.mm deleted file mode 100644 index 24133c0..0000000 --- a/ios/chrome/app/content_suggestions_scheduler_app_state_agent.mm +++ /dev/null
@@ -1,68 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#import "ios/chrome/app/content_suggestions_scheduler_app_state_agent.h" - -#include "components/ntp_snippets/content_suggestions_service.h" -#import "components/previous_session_info/previous_session_info.h" -#import "ios/chrome/app/application_delegate/app_state.h" -#include "ios/chrome/browser/ntp_snippets/ios_chrome_content_suggestions_service_factory.h" -#import "ios/chrome/browser/ui/main/scene_state.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@interface ContentSuggestionsSchedulerAppAgent () - -// Flag to keep track if we notified the service once at the cold app start. -@property(nonatomic, assign) BOOL hasNotifiedColdStart; - -@end - -@implementation ContentSuggestionsSchedulerAppAgent - -#pragma mark - SceneObservingAppAgent - -- (void)appDidEnterForeground { - [self notifyForeground]; -} - -#pragma mark - private - -// Convenience getter for the content suggestion service. -- (ntp_snippets::ContentSuggestionsService*)service { - if (!self.appState.mainBrowserState) { - return nil; - } - return IOSChromeContentSuggestionsServiceFactory::GetForBrowserState( - self.appState.mainBrowserState); -} - -// Notify the serivce about the cold start. -- (void)notifyColdStart { - if ([self service]) { - if ([PreviousSessionInfo sharedInstance] - .isFirstSessionAfterLanguageChange) { - [self service]->ClearAllCachedSuggestions(); - } - - [self service]->remote_suggestions_scheduler() -> OnBrowserColdStart(); - } -} - -// Notify the serivce when the app is brought to foreground. The first time this -// happens, also notify about a cold start. -- (void)notifyForeground { - if (!self.hasNotifiedColdStart) { - [self notifyColdStart]; - self.hasNotifiedColdStart = YES; - } - - if ([self service]) { - [self service]->remote_suggestions_scheduler() -> OnBrowserForegrounded(); - } -} - -@end
diff --git a/ios/chrome/app/main_controller.mm b/ios/chrome/app/main_controller.mm index 18ccb7d..09f976e 100644 --- a/ios/chrome/app/main_controller.mm +++ b/ios/chrome/app/main_controller.mm
@@ -36,7 +36,6 @@ #include "ios/chrome/app/app_metrics_app_state_agent.h" #import "ios/chrome/app/application_delegate/metrics_mediator.h" #import "ios/chrome/app/blocking_scene_commands.h" -#import "ios/chrome/app/content_suggestions_scheduler_app_state_agent.h" #import "ios/chrome/app/deferred_initialization_runner.h" #import "ios/chrome/app/enterprise_app_agent.h" #import "ios/chrome/app/first_run_app_state_agent.h" @@ -666,7 +665,6 @@ } - (void)addPostSafeModeAgents { - [self.appState addAgent:[[ContentSuggestionsSchedulerAppAgent alloc] init]]; [self.appState addAgent:[[EnterpriseAppAgent alloc] init]]; [self.appState addAgent:[[IncognitoUsageAppStateAgent alloc] init]]; [self.appState addAgent:[[FirstRunAppAgent alloc] init]];
diff --git a/ios/chrome/app/startup/BUILD.gn b/ios/chrome/app/startup/BUILD.gn index a53397aab..a412e94b 100644 --- a/ios/chrome/app/startup/BUILD.gn +++ b/ios/chrome/app/startup/BUILD.gn
@@ -80,7 +80,6 @@ "//ios/chrome/browser/browser_state", "//ios/chrome/browser/first_run", "//ios/chrome/browser/net:net", - "//ios/chrome/browser/ntp_snippets", "//ios/chrome/browser/ui/default_promo:utils", "//ios/chrome/browser/web:web_internal", "//ios/chrome/common",
diff --git a/ios/chrome/browser/DEPS b/ios/chrome/browser/DEPS index fc1a0ef8..47f71ab9 100644 --- a/ios/chrome/browser/DEPS +++ b/ios/chrome/browser/DEPS
@@ -47,7 +47,6 @@ "+components/leveldb_proto", "+components/lookalikes/core", "+components/metrics", - "+components/ntp_tiles", "+components/user_prefs", "+components/metrics_services_manager", "+components/navigation_metrics", @@ -151,6 +150,10 @@ "-components/metrics/gpu", "-components/sessions/content", + # ios/chrome/browser should not depend on ios/chrome/browser/ui + "-ios/chrome/browser/ui", + "-ios/common/ui", + # For tests. "+ios/chrome/test", "+ios/public/test", @@ -164,5 +167,23 @@ specific_include_rules = { ".*test\.mm": [ "+components/previous_session_info/previous_session_info_private.h", + # TODO(crbug.com/1294160): browser should not depend on UI, this is a + # blanket exception for tests. + "+ios/chrome/browser/ui", ], + + # TODO(crbug.com/1294160): Remove these dependencies. + "^browser_about_rewriter.cc": [ + "+ios/chrome/browser/ui/ui_feature_flags.h", + ], + "^chrome_root_coordinator.h": [ + "+ios/chrome/browser/ui/coordinators/chrome_coordinator.h", + ], + "^ios_chrome_field_trials.mm": [ + "+ios/chrome/browser/ui/first_run/fre_field_trial.h", + ], + "^system_flags.mm": [ + "+ios/chrome/browser/ui/ui_feature_flags.h", + ], + }
diff --git a/ios/chrome/browser/accessibility/DEPS b/ios/chrome/browser/accessibility/DEPS new file mode 100644 index 0000000..fb836a7 --- /dev/null +++ b/ios/chrome/browser/accessibility/DEPS
@@ -0,0 +1,6 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^window_accessibility_change_notifier_app_agent.mm": [ + "+ios/chrome/browser/ui/main/scene_state.h", + ], +}
diff --git a/ios/chrome/browser/autofill/DEPS b/ios/chrome/browser/autofill/DEPS index df25fea9..4b25f80 100644 --- a/ios/chrome/browser/autofill/DEPS +++ b/ios/chrome/browser/autofill/DEPS
@@ -4,4 +4,25 @@ "form_input_egtest\.mm": [ "+ios/web/public/test/http_server", ], + + # TODO(crbug.com/1294160): Remove these dependencies. + "^autofill_tab_helper.mm": [ + "+ios/chrome/browser/ui/autofill/chrome_autofill_client_ios.h", + ], + "^form_input_accessory_view_handler.mm": [ + "+ios/chrome/browser/ui/util/uikit_ui_util.h", + ], + "^form_suggestion_controller.mm": [ + "+ios/chrome/browser/ui/util/ui_util.h", + ], + "^form_suggestion_label.mm": [ + "+ios/chrome/browser/ui/util/uikit_ui_util.h", + "+ios/chrome/common/ui/colors/semantic_color_names.h", + "+ios/chrome/common/ui/util/constraints_ui_util.h", + ], + "^form_suggestion_view.mm": [ + "+ios/chrome/browser/ui/util/rtl_geometry.h", + "+ios/chrome/common/ui/util/constraints_ui_util.h", + ], + }
diff --git a/ios/chrome/browser/autofill/automation/DEPS b/ios/chrome/browser/autofill/automation/DEPS new file mode 100644 index 0000000..d00e9cf --- /dev/null +++ b/ios/chrome/browser/autofill/automation/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^automation_action.mm": [ + "+ios/chrome/browser/ui/infobars/infobar_constants.h", + ], +} +
diff --git a/ios/chrome/browser/browser_state/DEPS b/ios/chrome/browser/browser_state/DEPS index 836b651f..86841eb 100644 --- a/ios/chrome/browser/browser_state/DEPS +++ b/ios/chrome/browser/browser_state/DEPS
@@ -4,4 +4,10 @@ # access to that class. "+ios/web/webui/url_data_manager_ios_backend.h" ], + + # TODO(crbug.com/1294160): Remove this dependency. + "^browser_state_keyed_service_factories.mm": [ + "+ios/chrome/browser/ui/voice/text_to_speech_playback_controller_factory.h", + ], + }
diff --git a/ios/chrome/browser/commerce/DEPS b/ios/chrome/browser/commerce/DEPS index 12d1c0f6..6fc364b 100644 --- a/ios/chrome/browser/commerce/DEPS +++ b/ios/chrome/browser/commerce/DEPS
@@ -1,3 +1,11 @@ include_rules = [ "+components/commerce/core/proto", ] + +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^price_alert_util.mm": [ + "+ios/chrome/browser/ui/ui_feature_flags.h", + ], +} +
diff --git a/ios/chrome/browser/crash_report/DEPS b/ios/chrome/browser/crash_report/DEPS index 37e013e..6a33ca5 100644 --- a/ios/chrome/browser/crash_report/DEPS +++ b/ios/chrome/browser/crash_report/DEPS
@@ -4,3 +4,13 @@ # For fuzzer "+third_party/crashpad/crashpad", ] + +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^crash_restore_helper.mm": [ + "+ios/chrome/browser/ui/main/scene_state.h", + "+ios/chrome/browser/ui/main/scene_state_browser_agent.h", + "+ios/chrome/browser/ui/ui_feature_flags.h", + ], +} +
diff --git a/ios/chrome/browser/discover_feed/DEPS b/ios/chrome/browser/discover_feed/DEPS new file mode 100644 index 0000000..821a591 --- /dev/null +++ b/ios/chrome/browser/discover_feed/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^discover_feed_service.mm": [ + "+ios/chrome/browser/ui/ntp/feed_metrics_recorder.h", + ], +} +
diff --git a/ios/chrome/browser/download/DEPS b/ios/chrome/browser/download/DEPS new file mode 100644 index 0000000..a6504b7 --- /dev/null +++ b/ios/chrome/browser/download/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^browser_download_service.mm": [ + "+ios/chrome/browser/ui/download/features.h", + ], +} +
diff --git a/ios/chrome/browser/favicon/DEPS b/ios/chrome/browser/favicon/DEPS new file mode 100644 index 0000000..f0047f78 --- /dev/null +++ b/ios/chrome/browser/favicon/DEPS
@@ -0,0 +1,8 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^favicon_loader.mm": [ + "+ios/chrome/browser/ui/util/uikit_ui_util.h", + "+ios/chrome/common/ui/favicon/favicon_attributes.h", + ], +} +
diff --git a/ios/chrome/browser/feature_engagement/DEPS b/ios/chrome/browser/feature_engagement/DEPS new file mode 100644 index 0000000..9d78971 --- /dev/null +++ b/ios/chrome/browser/feature_engagement/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^tracker_util.mm": [ + "+ios/chrome/browser/ui/commands/open_new_tab_command.h", + ], +} +
diff --git a/ios/chrome/browser/flags/DEPS b/ios/chrome/browser/flags/DEPS new file mode 100644 index 0000000..f8785d56 --- /dev/null +++ b/ios/chrome/browser/flags/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^about_flags.mm": [ + "+ios/chrome/browser/ui", + ], +} +
diff --git a/ios/chrome/browser/follow/DEPS b/ios/chrome/browser/follow/DEPS new file mode 100644 index 0000000..e59b4274 --- /dev/null +++ b/ios/chrome/browser/follow/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^follow_java_script_feature.h": [ + "+ios/chrome/browser/ui/follow/follow_site_info.h", + ], +} +
diff --git a/ios/chrome/browser/google/DEPS b/ios/chrome/browser/google/DEPS new file mode 100644 index 0000000..245bff8 --- /dev/null +++ b/ios/chrome/browser/google/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^google_logo_service.mm": [ + "+ios/chrome/browser/ui/util/ui_util.h", + ], +} +
diff --git a/ios/chrome/browser/infobars/DEPS b/ios/chrome/browser/infobars/DEPS new file mode 100644 index 0000000..197f0f7 --- /dev/null +++ b/ios/chrome/browser/infobars/DEPS
@@ -0,0 +1,23 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^infobar_badge_model.h": [ + "+ios/chrome/browser/ui/badges/badge_item.h", + ], + "^infobar_badge_model.mm": [ + "+ios/chrome/browser/ui/badges/badge_type_util.h", + ], + "^infobar_badge_tab_helper.h": [ + "+ios/chrome/browser/ui/badges/badge_item.h", + ], + "^infobar_badge_tab_helper.mm": [ + "+ios/chrome/browser/ui/badges/badge_type_util.h", + ], + "^infobar_metrics_recorder.h": [ + "+ios/chrome/browser/ui/default_promo/default_browser_utils.h", + ], + "^infobar_metrics_recorder.mm": [ + "+ios/chrome/browser/ui/default_promo/default_browser_utils.h", + ], + +} +
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/DEPS b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/DEPS new file mode 100644 index 0000000..e5b4715 --- /dev/null +++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/autofill_address_profile/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^save_address_profile_infobar_modal_interaction_handler.mm": [ + "+ios/chrome/browser/ui/autofill/autofill_ui_type_util.h", + ], +} +
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/DEPS b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/DEPS new file mode 100644 index 0000000..4afc018a8 --- /dev/null +++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/passwords/DEPS
@@ -0,0 +1,12 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^password_infobar_modal_interaction_handler.mm": [ + "+ios/chrome/browser/ui/commands/application_commands.h", + "+ios/chrome/browser/ui/commands/command_dispatcher.h", + ], + "^password_infobar_modal_interaction_handler.mm": [ + "+ios/chrome/browser/ui/commands/application_commands.h", + "+ios/chrome/browser/ui/commands/command_dispatcher.h", + ] +} +
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/reading_list/DEPS b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/reading_list/DEPS new file mode 100644 index 0000000..ea07b0b --- /dev/null +++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/reading_list/DEPS
@@ -0,0 +1,15 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^add_to_reading_list_infobar_banner_interaction_handler.mm": [ + "+ios/chrome/browser/ui/commands/browser_commands.h", + "+ios/chrome/browser/ui/commands/command_dispatcher.h", + "+ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.h", + ], + "^add_to_reading_list_modal_infobar_interaction_handler.mm": [ + "+ios/chrome/browser/ui/commands/browser_commands.h", + "+ios/chrome/browser/ui/commands/command_dispatcher.h", + "+ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.h", + ], + +} +
diff --git a/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/DEPS b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/DEPS new file mode 100644 index 0000000..60fdce8 --- /dev/null +++ b/ios/chrome/browser/infobars/overlays/browser_agent/interaction_handlers/test/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^mock_ios_add_to_reading_list_infobar_delegate.h": [ + "+ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.h", + ], +} +
diff --git a/ios/chrome/browser/infobars/test/DEPS b/ios/chrome/browser/infobars/test/DEPS new file mode 100644 index 0000000..145e27d --- /dev/null +++ b/ios/chrome/browser/infobars/test/DEPS
@@ -0,0 +1,14 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^ios_add_to_reading_list_infobar_delegate.h": [ + "+ios/chrome/browser/ui/badges/badge_type.h", + ], + "^fake_infobar_badge_tab_helper_delegate.h": [ + "+ios/chrome/browser/ui/badges/badge_type.h", + ], + "^fake_infobar_badge_tab_helper_delegate.mm": [ + "+ios/chrome/browser/ui/badges/badge_item.h", + ], + +} +
diff --git a/ios/chrome/browser/main/DEPS b/ios/chrome/browser/main/DEPS new file mode 100644 index 0000000..ffbb6ed --- /dev/null +++ b/ios/chrome/browser/main/DEPS
@@ -0,0 +1,13 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^browser_agent_util.mm": [ + "+ios/chrome/browser/ui/start_surface/start_surface_recent_tab_browser_agent.h", + ], + "^browser_impl.mm": [ + "+ios/chrome/browser/ui/commands/command_dispatcher.h", + ], + "^test_browser.mm": [ + "+ios/chrome/browser/ui/commands/command_dispatcher.h", + ] +} +
diff --git a/ios/chrome/browser/memory/DEPS b/ios/chrome/browser/memory/DEPS new file mode 100644 index 0000000..6cc5805e --- /dev/null +++ b/ios/chrome/browser/memory/DEPS
@@ -0,0 +1,8 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^memory_debugger.mm": [ + "+ios/chrome/browser/ui/util", + "+ios/chrome/common/ui/util/device_util.h", + ], +} +
diff --git a/ios/chrome/browser/metrics/DEPS b/ios/chrome/browser/metrics/DEPS index 96d839d..ae8adb8 100644 --- a/ios/chrome/browser/metrics/DEPS +++ b/ios/chrome/browser/metrics/DEPS
@@ -8,4 +8,19 @@ "metrics_app_interface\.mm": [ "+third_party/zlib/google/compression_utils.h", ], + + # TODO(crbug.com/1294160): Remove these dependencies. + "^incognito_usage_app_state_agent.mm": [ + "+ios/chrome/browser/ui/main/scene_state.h", + ], + "^ios_chrome_default_browser_metrics_provider.mm": [ + "+ios/chrome/browser/ui/default_promo/default_browser_utils.h", + ], + "^ios_chrome_metrics_service_client.mm": [ + "+ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h", + ], + "^user_interface_style_recorder.mm": [ + "+ios/chrome/browser/ui/util/ui_util.h", + ], + }
diff --git a/ios/chrome/browser/ntp_snippets/DEPS b/ios/chrome/browser/ntp_snippets/DEPS new file mode 100644 index 0000000..1365eff8 --- /dev/null +++ b/ios/chrome/browser/ntp_snippets/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^ios_chrome_content_suggestions_service_factory_util.mm": [ + "+ios/chrome/browser/ui/ui_feature_flags.h", + ], +} +
diff --git a/ios/chrome/browser/omaha/DEPS b/ios/chrome/browser/omaha/DEPS new file mode 100644 index 0000000..396b7fb --- /dev/null +++ b/ios/chrome/browser/omaha/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^omaha_service.mm": [ + "+ios/chrome/browser/ui/util/ui_util.h", + ], +} +
diff --git a/ios/chrome/browser/open_in/DEPS b/ios/chrome/browser/open_in/DEPS new file mode 100644 index 0000000..70949eff7 --- /dev/null +++ b/ios/chrome/browser/open_in/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^open_in_tab_helper.mm": [ + "+ios/chrome/browser/ui/ui_feature_flags.h", + ], +} +
diff --git a/ios/chrome/browser/overlays/public/common/infobars/DEPS b/ios/chrome/browser/overlays/public/common/infobars/DEPS new file mode 100644 index 0000000..e6fd773 --- /dev/null +++ b/ios/chrome/browser/overlays/public/common/infobars/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^infobar_overlay_request_config.mm": [ + "+ios/chrome/browser/ui/badges/badge_type_util.h", + ], +} +
diff --git a/ios/chrome/browser/overlays/public/infobar_banner/DEPS b/ios/chrome/browser/overlays/public/infobar_banner/DEPS new file mode 100644 index 0000000..16cbd20 --- /dev/null +++ b/ios/chrome/browser/overlays/public/infobar_banner/DEPS
@@ -0,0 +1,11 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^add_to_reading_list_infobar_banner_overlay_request_config.mm": [ + "+ios/chrome/browser/ui/reading_list/ios_add_to_reading_list_infobar_delegate.h", + ], + "^confirm_infobar_banner_overlay_request_config.mm": [ + "+ios/chrome/browser/ui/authentication/signin_notification_infobar_delegate.h", + ], + +} +
diff --git a/ios/chrome/browser/overlays/public/infobar_modal/DEPS b/ios/chrome/browser/overlays/public/infobar_modal/DEPS new file mode 100644 index 0000000..51c9428 --- /dev/null +++ b/ios/chrome/browser/overlays/public/infobar_modal/DEPS
@@ -0,0 +1,11 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^save_address_profile_infobar_modal_overlay_request_config.mm": [ + "+ios/chrome/browser/ui/autofill/autofill_ui_type_util.h", + ], + "^save_card_infobar_modal_overlay_request_config.mm": [ + "+ios/chrome/browser/ui/autofill/save_card_message_with_links.h", + ], + +} +
diff --git a/ios/chrome/browser/overlays/public/web_content_area/DEPS b/ios/chrome/browser/overlays/public/web_content_area/DEPS new file mode 100644 index 0000000..b471c95a3 --- /dev/null +++ b/ios/chrome/browser/overlays/public/web_content_area/DEPS
@@ -0,0 +1,13 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^http_auth_overlay.mm": [ + "+ios/chrome/browser/ui/elements/text_field_configuration.h", + ], + "^java_script_dialog_overlay.mm": [ + "+ios/chrome/browser/ui/dialogs/dialog_constants.h", + "+ios/chrome/browser/ui/dialogs/java_script_dialog_blocking_state.h", + "+ios/chrome/browser/ui/elements/text_field_configuration.h", + ], + +} +
diff --git a/ios/chrome/browser/overscroll_actions/DEPS b/ios/chrome/browser/overscroll_actions/DEPS new file mode 100644 index 0000000..6976565 --- /dev/null +++ b/ios/chrome/browser/overscroll_actions/DEPS
@@ -0,0 +1,11 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^overscroll_actions_tab_helper.h": [ + "+ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h", + ], + "^overscroll_actions_tab_helper.mm": [ + "+ios/chrome/browser/ui/overscroll_actions/overscroll_actions_controller.h", + ], + +} +
diff --git a/ios/chrome/browser/passwords/DEPS b/ios/chrome/browser/passwords/DEPS new file mode 100644 index 0000000..70aea66 --- /dev/null +++ b/ios/chrome/browser/passwords/DEPS
@@ -0,0 +1,19 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^ios_chrome_password_manager_client.mm": [ + "+ios/chrome/browser/ui/ui_feature_flags.h", + ], + "^notify_auto_signin_view_controller.mm": [ + "+ios/chrome/browser/ui/util/rtl_geometry.h", + "+ios/chrome/browser/ui/util/uikit_ui_util.h", + ], + "^password_controller.mm": [ + "+ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h", + "+ios/chrome/browser/ui/commands/application_commands.h", + "+ios/chrome/browser/ui/commands/command_dispatcher.h", + "+ios/chrome/browser/ui/commands/password_breach_commands.h", + "+ios/chrome/browser/ui/commands/password_protection_commands.h", + ], + +} +
diff --git a/ios/chrome/browser/policy/DEPS b/ios/chrome/browser/policy/DEPS new file mode 100644 index 0000000..319a4b5 --- /dev/null +++ b/ios/chrome/browser/policy/DEPS
@@ -0,0 +1,10 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^policy_watcher_browser_agent.mm": [ + "+ios/chrome/browser/ui/authentication/signin/signin_utils.h", + "+ios/chrome/browser/ui/commands/policy_change_commands.h", + "+ios/chrome/browser/ui/main/scene_state.h", + "+ios/chrome/browser/ui/main/scene_state_browser_agent.h", + ], +} +
diff --git a/ios/chrome/browser/prefs/DEPS b/ios/chrome/browser/prefs/DEPS new file mode 100644 index 0000000..8317b44 --- /dev/null +++ b/ios/chrome/browser/prefs/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^browser_prefs.mm": [ + "+ios/chrome/browser/ui", + ], +} +
diff --git a/ios/chrome/browser/prerender/DEPS b/ios/chrome/browser/prerender/DEPS new file mode 100644 index 0000000..e50c5364 --- /dev/null +++ b/ios/chrome/browser/prerender/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^prerender_service_impl.mm": [ + "+ios/chrome/browser/ui/ntp/ntp_util.h", + ], +} +
diff --git a/ios/chrome/browser/providers/signin/DEPS b/ios/chrome/browser/providers/signin/DEPS new file mode 100644 index 0000000..e7284616 --- /dev/null +++ b/ios/chrome/browser/providers/signin/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^chromium_signin_resources.mm": [ + "+ios/chrome/browser/ui/util/uikit_ui_util.h", + ], +} +
diff --git a/ios/chrome/browser/providers/ui_utils/DEPS b/ios/chrome/browser/providers/ui_utils/DEPS new file mode 100644 index 0000000..9dcb9ca --- /dev/null +++ b/ios/chrome/browser/providers/ui_utils/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^chromium_logo_controller.h": [ + "+ios/chrome/browser/ui/ntp/logo_vendor.h", + ], +} +
diff --git a/ios/chrome/browser/reading_list/DEPS b/ios/chrome/browser/reading_list/DEPS new file mode 100644 index 0000000..8dcd7c7 --- /dev/null +++ b/ios/chrome/browser/reading_list/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^reading_list_distiller_page.mm": [ + "+ios/chrome/browser/ui/util/uikit_ui_util.h", + ], +} +
diff --git a/ios/chrome/browser/safe_browsing/safe_browsing_blocking_page.mm b/ios/chrome/browser/safe_browsing/safe_browsing_blocking_page.mm index be9c1f42..6b805ce 100644 --- a/ios/chrome/browser/safe_browsing/safe_browsing_blocking_page.mm +++ b/ios/chrome/browser/safe_browsing/safe_browsing_blocking_page.mm
@@ -81,27 +81,6 @@ } } // namespace -namespace safe_browsing { -SafeBrowsingMetricsCollector::EventType GetEventTypeFromThreatSource( - ThreatSource threat_source) { - switch (threat_source) { - case ThreatSource::LOCAL_PVER4: - case ThreatSource::REMOTE: - return SafeBrowsingMetricsCollector::EventType:: - DATABASE_INTERSTITIAL_BYPASS; - case ThreatSource::CLIENT_SIDE_DETECTION: - return SafeBrowsingMetricsCollector::EventType::CSD_INTERSTITIAL_BYPASS; - case ThreatSource::REAL_TIME_CHECK: - return SafeBrowsingMetricsCollector::EventType:: - REAL_TIME_INTERSTITIAL_BYPASS; - default: - NOTREACHED() << "Unexpected threat source."; - return SafeBrowsingMetricsCollector::EventType:: - DATABASE_INTERSTITIAL_BYPASS; - } -} -} // safe_browsing - #pragma mark - SafeBrowsingBlockingPage // static @@ -203,8 +182,7 @@ safe_browsing::SafeBrowsingMetricsCollector* metrics_collector = SafeBrowsingMetricsCollectorFactory::GetForBrowserState(browser_state); if (metrics_collector) { - metrics_collector->AddSafeBrowsingEventToPref( - GetEventTypeFromThreatSource(threat_source_)); + metrics_collector->AddBypassEventToPref(threat_source_); } } Reload();
diff --git a/ios/chrome/browser/screenshot/DEPS b/ios/chrome/browser/screenshot/DEPS new file mode 100644 index 0000000..31269cc --- /dev/null +++ b/ios/chrome/browser/screenshot/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^screenshot_delegate.mm": [ + "+ios/chrome/browser/ui/main/browser_interface_provider.h", + ], +} +
diff --git a/ios/chrome/browser/sessions/DEPS b/ios/chrome/browser/sessions/DEPS new file mode 100644 index 0000000..2f19ad2 --- /dev/null +++ b/ios/chrome/browser/sessions/DEPS
@@ -0,0 +1,11 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^session_saving_scene_agent.h": [ + "+ios/chrome/browser/ui/main/observing_scene_state_agent.h", + ], + "^session_saving_scene_agent.mm": [ + "+ios/chrome/browser/ui/main/browser_interface_provider.h", + ], + +} +
diff --git a/ios/chrome/browser/signin/DEPS b/ios/chrome/browser/signin/DEPS new file mode 100644 index 0000000..93672f5 --- /dev/null +++ b/ios/chrome/browser/signin/DEPS
@@ -0,0 +1,16 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^account_consistency_browser_agent.mm": [ + "+ios/chrome/browser/ui/commands/application_commands.h", + "+ios/chrome/browser/ui/commands/open_new_tab_command.h", + "+ios/chrome/browser/ui/commands/show_signin_command.h", + ], + "^authentication_service.mm": [ + "+ios/chrome/browser/ui/authentication/signin/signin_utils.h", + ], + "^chrome_account_manager_service.mm": [ + "+ios/chrome/browser/ui/util/ui_util.h", + "+ios/chrome/browser/ui/util/uikit_ui_util.h", + ], +} +
diff --git a/ios/chrome/browser/snapshots/DEPS b/ios/chrome/browser/snapshots/DEPS new file mode 100644 index 0000000..3b3760e --- /dev/null +++ b/ios/chrome/browser/snapshots/DEPS
@@ -0,0 +1,14 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^snapshot_cache.mm": [ + "+ios/chrome/browser/ui/util/uikit_ui_util.h", + ], + "^snapshot_generator.mm": [ + "+ios/chrome/browser/ui/util/uikit_ui_util.h", + ], + "^snapshot_tab_helper.mm": [ + "+ios/chrome/browser/ui/util/ui_util.h", + ], + +} +
diff --git a/ios/chrome/browser/store_kit/DEPS b/ios/chrome/browser/store_kit/DEPS new file mode 100644 index 0000000..115c499 --- /dev/null +++ b/ios/chrome/browser/store_kit/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^store_kit_coordinator.h": [ + "+ios/chrome/browser/ui/coordinators/chrome_coordinator.h", + ], +} +
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 b8addde..775fc3cf 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
@@ -150,6 +150,8 @@ web::WebState* web_state) { if (batch_in_progress_) return; + if (!web_state->IsRealized()) + return; sync_sessions::SyncedTabDelegate* tab = GetSyncedTabDelegateFromWebState(web_state); if (!tab)
diff --git a/ios/chrome/browser/tabs/DEPS b/ios/chrome/browser/tabs/DEPS new file mode 100644 index 0000000..728f9b5 --- /dev/null +++ b/ios/chrome/browser/tabs/DEPS
@@ -0,0 +1,8 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^tab_helper_util.mm": [ + "+ios/chrome/browser/ui/download/features.h", + "+ios/chrome/browser/ui/ui_feature_flags.h", + ], +} +
diff --git a/ios/chrome/browser/tabs_search/DEPS b/ios/chrome/browser/tabs_search/DEPS new file mode 100644 index 0000000..6ff64798 --- /dev/null +++ b/ios/chrome/browser/tabs_search/DEPS
@@ -0,0 +1,12 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^tabs_search_service.h": [ + "+ios/chrome/browser/ui/history/ios_browsing_history_driver.h", + "+ios/chrome/browser/ui/history/ios_browsing_history_driver_delegate.h", + ], + "^tabs_search_service.mm": [ + "+ios/chrome/browser/ui/recent_tabs/synced_sessions.h", + ], + +} +
diff --git a/ios/chrome/browser/ui/DEPS b/ios/chrome/browser/ui/DEPS index 2084452..c88024e 100644 --- a/ios/chrome/browser/ui/DEPS +++ b/ios/chrome/browser/ui/DEPS
@@ -1,3 +1,7 @@ +include_rules = [ +"+ios/chrome/browser/ui", +] + specific_include_rules = { # web::HttpServer is deprecated in favor of net::EmbeddedTestServer. # TODO:(crbug.com/891834) Remove this exception.
diff --git a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm index e36b16c..b37cb46 100644 --- a/ios/chrome/browser/ui/browser_view/browser_view_controller.mm +++ b/ios/chrome/browser/ui/browser_view/browser_view_controller.mm
@@ -1120,9 +1120,6 @@ web::WebState* webState = self.currentWebState; if (webState) { - if (self.isNTPActiveForCurrentWebState) { - [[self ntpCoordinatorForWebState:webState] dismissModals]; - } [self.dispatcher closeFindInPage]; [self.textZoomHandler closeTextZoom]; }
diff --git a/ios/chrome/browser/ui/content_suggestions/BUILD.gn b/ios/chrome/browser/ui/content_suggestions/BUILD.gn index ecb24bbc..c9a4cd9 100644 --- a/ios/chrome/browser/ui/content_suggestions/BUILD.gn +++ b/ios/chrome/browser/ui/content_suggestions/BUILD.gn
@@ -4,8 +4,6 @@ source_set("content_suggestions") { sources = [ - "content_suggestions_alert_factory.h", - "content_suggestions_alert_factory.mm", "content_suggestions_category_wrapper.h", "content_suggestions_category_wrapper.mm", "content_suggestions_coordinator.h",
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.h deleted file mode 100644 index 1372f037..0000000 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.h +++ /dev/null
@@ -1,31 +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 IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ALERT_FACTORY_H_ -#define IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ALERT_FACTORY_H_ - -#import <UIKit/UIKit.h> - -@class AlertCoordinator; -class Browser; -@protocol ContentSuggestionsGestureCommands; -@class ContentSuggestionsMostVisitedItem; - -// Factory for AlertCoordinators for ContentSuggestions. -@interface ContentSuggestionsAlertFactory : NSObject - -// Same as above but for a MostVisited item. -+ (AlertCoordinator*) - alertCoordinatorForMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item - onViewController: - (UICollectionViewController*)viewController - withBrowser:(Browser*)browser - atPoint:(CGPoint)touchLocation - atIndexPath:(NSIndexPath*)indexPath - commandHandler:(id<ContentSuggestionsGestureCommands>) - commandHandler; - -@end - -#endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_ALERT_FACTORY_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.mm deleted file mode 100644 index 3d5f830..0000000 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.mm +++ /dev/null
@@ -1,94 +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 "ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.h" - -#include "ios/chrome/browser/browser_state/chrome_browser_state.h" -#import "ios/chrome/browser/main/browser.h" -#import "ios/chrome/browser/policy/policy_util.h" -#import "ios/chrome/browser/ui/alert_coordinator/action_sheet_coordinator.h" -#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_gesture_commands.h" -#import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h" -#include "ios/chrome/grit/ios_strings.h" -#include "ui/base/l10n/l10n_util.h" -#include "ui/strings/grit/ui_strings.h" - -#if !defined(__has_feature) || !__has_feature(objc_arc) -#error "This file requires ARC support." -#endif - -@implementation ContentSuggestionsAlertFactory - -+ (AlertCoordinator*) - alertCoordinatorForMostVisitedItem:(ContentSuggestionsMostVisitedItem*)item - onViewController: - (UICollectionViewController*)viewController - withBrowser:(Browser*)browser - atPoint:(CGPoint)touchLocation - atIndexPath:(NSIndexPath*)indexPath - commandHandler:(id<ContentSuggestionsGestureCommands>) - commandHandler { - AlertCoordinator* alertCoordinator = [[ActionSheetCoordinator alloc] - initWithBaseViewController:viewController - browser:browser - title:nil - message:nil - rect:CGRectMake(touchLocation.x, touchLocation.y, 0, - 0) - view:viewController.collectionView]; - - __weak ContentSuggestionsMostVisitedItem* weakItem = item; - __weak id<ContentSuggestionsGestureCommands> weakCommandHandler = - commandHandler; - - [alertCoordinator - addItemWithTitle:l10n_util::GetNSStringWithFixup( - IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWTAB) - action:^{ - ContentSuggestionsMostVisitedItem* strongItem = weakItem; - if (strongItem) { - [weakCommandHandler - openNewTabWithMostVisitedItem:strongItem - incognito:NO - atIndex:indexPath.item]; - } - } - style:UIAlertActionStyleDefault]; - - BOOL incognitoEnabled = - !IsIncognitoModeDisabled(browser->GetBrowserState()->GetPrefs()); - [alertCoordinator - addItemWithTitle:l10n_util::GetNSStringWithFixup( - IDS_IOS_CONTENT_CONTEXT_OPENLINKNEWINCOGNITOTAB) - action:^{ - ContentSuggestionsMostVisitedItem* strongItem = weakItem; - if (strongItem) { - [weakCommandHandler - openNewTabWithMostVisitedItem:strongItem - incognito:YES - atIndex:indexPath.item]; - } - } - style:UIAlertActionStyleDefault - enabled:incognitoEnabled]; - - [alertCoordinator - addItemWithTitle:l10n_util::GetNSStringWithFixup( - IDS_IOS_CONTENT_SUGGESTIONS_REMOVE) - action:^{ - ContentSuggestionsMostVisitedItem* strongItem = weakItem; - if (strongItem) { - [weakCommandHandler removeMostVisited:strongItem]; - } - } - style:UIAlertActionStyleDestructive]; - - [alertCoordinator addItemWithTitle:l10n_util::GetNSString(IDS_APP_CANCEL) - action:nil - style:UIAlertActionStyleCancel]; - - return alertCoordinator; -} - -@end
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h index a3d08c4..1f2cc99 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_commands.h
@@ -21,13 +21,6 @@ - (void)openMostRecentTab; // Handles the action that dismisses the "Return to Recent Tab" item. - (void)hideMostRecentTab; -// Displays a context menu for the |mostVisitedItem|. -- (void)displayContextMenuForMostVisitedItem: - (CollectionViewItem*)mostVisitedItem - atPoint:(CGPoint)touchLocation - atIndexPath:(NSIndexPath*)indexPath; -// Dismisses the context menu if it is displayed. -- (void)dismissModals; // Handles the actions following a tap on the promo. - (void)handlePromoTapped; // Handles the actions following a tap on the "Manage Activity" item in the
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h index 0cd5e00..dfc4c47 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.h
@@ -57,9 +57,6 @@ // Delegate used to communicate to communicate events to the DiscoverFeed. @property(nonatomic, weak) id<DiscoverFeedDelegate> discoverFeedDelegate; -// Dismisses all modals owned by the NTP mediator. -- (void)dismissModals; - // Stop any scrolling in the scroll view. - (void)stopScrolling;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm index 7504ebc..8eff6e1 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_coordinator.mm
@@ -305,29 +305,16 @@ #pragma mark - ContentSuggestionsHeaderCommands -- (void)prepareForVoiceSearchPresentation { - [self.ntpMediator dismissModals]; -} - - (void)updateForHeaderSizeChange { [self.ntpCommandHandler updateDiscoverFeedLayout]; } -- (void)updateForLocationBarResignedFirstResponder { - // TODO(crbug.com/1200303): Check if doing this is actually needed. - [self.ntpMediator dismissModals]; -} - #pragma mark - Public methods - (UIView*)view { return self.suggestionsViewController.view; } -- (void)dismissModals { - [self.ntpMediator dismissModals]; -} - - (void)stopScrolling { UIScrollView* scrollView = self.suggestionsViewController.collectionView; [scrollView setContentOffset:scrollView.contentOffset animated:NO];
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_commands.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_commands.h index 969b3fc..75c3f04 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_commands.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_commands.h
@@ -9,17 +9,10 @@ // interact with the coordinator layer. @protocol ContentSuggestionsHeaderCommands -// Informs the receiver that voice Search will be presented. -- (void)prepareForVoiceSearchPresentation; - // Informs the receiver that the ContentSuggestionsHeaderViewController's size // has changed. - (void)updateForHeaderSizeChange; -// Informs the receiver that the header's Location Bar has resigned first -// responder. -- (void)updateForLocationBarResignedFirstResponder; - @end #endif // IOS_CHROME_BROWSER_UI_CONTENT_SUGGESTIONS_CONTENT_SUGGESTIONS_HEADER_COMMANDS_H_
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm index 04702f1..8464cb8 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller.mm
@@ -394,8 +394,6 @@ } - (void)loadVoiceSearch:(id)sender { - [self.commandHandler prepareForVoiceSearchPresentation]; - if ([self.delegate ignoreLoadRequests]) return; DCHECK(self.voiceSearchIsEnabled); @@ -706,12 +704,8 @@ return; self.omniboxFocused = NO; - if ([self.delegate isContextMenuVisible]) { - return; - } [self shiftTilesDown]; - [self.commandHandler updateForLocationBarResignedFirstResponder]; } - (void)setVoiceSearchIsEnabled:(BOOL)voiceSearchIsEnabled {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller_delegate.h b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller_delegate.h index 2bd76e3..f63e25d 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller_delegate.h +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view_controller_delegate.h
@@ -12,9 +12,6 @@ // Delegate for the ContentSuggestionsHeaderViewController. @protocol ContentSuggestionsHeaderViewControllerDelegate -// Returns whether a context menu is visible. -- (BOOL)isContextMenuVisible; - // Returns whether the collection is scrolled to the omnibox. - (BOOL)isScrolledToMinimumHeight;
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm index 8d2dfa57..7f51995 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_view_controller.mm
@@ -107,10 +107,7 @@ [self.collectionView deleteSections:[NSIndexSet indexSetWithIndex:section]]; } - completion:^(BOOL) { - // The context menu could be displayed for the deleted entries. - [self.suggestionCommandHandler dismissModals]; - }]; + completion:nil]; } #pragma mark - UIViewController
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm index 925d92d..1c624b8 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_mediator.mm
@@ -24,7 +24,6 @@ #import "ios/chrome/browser/signin/authentication_service.h" #import "ios/chrome/browser/signin/chrome_account_manager_service.h" #import "ios/chrome/browser/signin/chrome_account_manager_service_observer_bridge.h" -#import "ios/chrome/browser/ui/alert_coordinator/alert_coordinator.h" #import "ios/chrome/browser/ui/commands/application_commands.h" #import "ios/chrome/browser/ui/commands/browser_commands.h" #import "ios/chrome/browser/ui/commands/omnibox_commands.h" @@ -34,7 +33,6 @@ #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_action_item.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_most_visited_item.h" #import "ios/chrome/browser/ui/content_suggestions/cells/content_suggestions_return_to_recent_tab_item.h" -#import "ios/chrome/browser/ui/content_suggestions/content_suggestions_alert_factory.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_collection_utils.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_feature.h" #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_header_synchronizer.h" @@ -101,7 +99,6 @@ } @property(nonatomic, assign) ChromeAccountManagerService* accountManagerService; -@property(nonatomic, strong) AlertCoordinator* alertCoordinator; // TemplateURL used to get the search engine. @property(nonatomic, assign) TemplateURLService* templateURLService; // Authentication Service to get the current user's avatar. @@ -290,37 +287,6 @@ _URLLoader->Load(params); } -- (void)displayContextMenuForMostVisitedItem:(CollectionViewItem*)item - atPoint:(CGPoint)touchLocation - atIndexPath:(NSIndexPath*)indexPath { - DCHECK(_browser); - // No context menu for action buttons. - if ([item isKindOfClass:[ContentSuggestionsMostVisitedActionItem class]]) { - return; - } - - // Unfocus the omnibox as the omnibox can disappear when choosing some - // options. See crbug.com/928237. - [self.dispatcher cancelOmniboxEdit]; - - ContentSuggestionsMostVisitedItem* mostVisitedItem = - base::mac::ObjCCastStrict<ContentSuggestionsMostVisitedItem>(item); - self.alertCoordinator = [ContentSuggestionsAlertFactory - alertCoordinatorForMostVisitedItem:mostVisitedItem - onViewController:self.suggestionsViewController - withBrowser:self.browser - atPoint:touchLocation - atIndexPath:indexPath - commandHandler:self]; - - [self.alertCoordinator start]; -} - -- (void)dismissModals { - [self.alertCoordinator stop]; - self.alertCoordinator = nil; -} - // TODO(crbug.com/761096) : Promo handling should be tested. - (void)handlePromoTapped { NotificationPromoWhatsNew* notificationPromo = @@ -453,10 +419,6 @@ #pragma mark - ContentSuggestionsHeaderViewControllerDelegate -- (BOOL)isContextMenuVisible { - return self.alertCoordinator.isVisible; -} - - (BOOL)isScrolledToMinimumHeight { return [self.ntpViewController isScrolledToMinimumHeight]; }
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h index e83969b..1948241 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h +++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.h
@@ -48,9 +48,6 @@ // Bubble presenter for displaying IPH bubbles relating to the NTP. @property(nonatomic, strong) BubblePresenter* bubblePresenter; -// Dismisses all modals owned by the NTP. -- (void)dismissModals; - // Animates the NTP fakebox to the focused position and focuses the real // omnibox. - (void)focusFakebox;
diff --git a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm index 8a2cc9a..c2ecd56 100644 --- a/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm +++ b/ios/chrome/browser/ui/ntp/new_tab_page_coordinator.mm
@@ -454,10 +454,6 @@ _webState = webState; } -- (void)dismissModals { - [self.contentSuggestionsCoordinator dismissModals]; -} - - (void)stopScrolling { if (!self.contentSuggestionsCoordinator) { return;
diff --git a/ios/chrome/browser/upgrade/DEPS b/ios/chrome/browser/upgrade/DEPS new file mode 100644 index 0000000..cf5b4cf --- /dev/null +++ b/ios/chrome/browser/upgrade/DEPS
@@ -0,0 +1,8 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^upgrade_center.mm": [ + "+ios/chrome/browser/ui/commands/application_commands.h", + "+ios/chrome/browser/ui/commands/open_new_tab_command.h", + ], +} +
diff --git a/ios/chrome/browser/url_loading/DEPS b/ios/chrome/browser/url_loading/DEPS new file mode 100644 index 0000000..fb3f11df --- /dev/null +++ b/ios/chrome/browser/url_loading/DEPS
@@ -0,0 +1,15 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove these dependencies. + "^url_loading_browser_agent.mm": [ + "+ios/chrome/browser/ui/commands/open_new_tab_command.h", + "+ios/chrome/browser/ui/incognito_reauth/incognito_reauth_scene_agent.h", + "+ios/chrome/browser/ui/main/scene_state_browser_agent.h", + "+ios/chrome/browser/ui/ntp/ntp_util.h", + "+ios/chrome/browser/ui/ui_feature_flags.h", + ], + "^url_loading_params.h": [ + "+ios/chrome/browser/ui/commands/open_new_tab_command.h", + ], + +} +
diff --git a/ios/chrome/browser/web/DEPS b/ios/chrome/browser/web/DEPS index 46d60a2..6c4acc55 100644 --- a/ios/chrome/browser/web/DEPS +++ b/ios/chrome/browser/web/DEPS
@@ -59,4 +59,30 @@ "window_open_by_dom_egtest\.mm": [ "+ios/web/public/test/http_server", ], + + # TODO(crbug.com/1294160): Remove these dependencies. + "^chrome_web_client.mm": [ + "+ios/chrome/browser/ui/elements/windowed_container_view.h", + "+ios/chrome/browser/ui/reading_list/reading_list_features.h", + "+ios/chrome/browser/ui/reading_list/reading_list_javascript_feature.h", + "+ios/chrome/browser/ui/ui_feature_flags.h", + ], + "^page_placeholder_tab_helper.h": [ + "+ios/chrome/browser/ui/elements/top_aligned_image_view.h", + ], + "^page_placeholder_tab_helper.mm": [ + "+ios/chrome/browser/ui/util/named_guide.h", + ], + "^sad_tab_tab_helper.mm": [ + "+ios/chrome/browser/ui/fullscreen/fullscreen_controller.h", + "+ios/chrome/browser/ui/fullscreen/scoped_fullscreen_disabler.h", + ], + "^web_state_delegate_browser_agent.h": [ + "+ios/chrome/browser/ui/dialogs/overlay_java_script_dialog_presenter.h", + ], + "^web_state_delegate_browser_agent.mm": [ + "+ios/chrome/browser/ui/dialogs/nsurl_protection_space_util.h", + "+ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.h", + ], + }
diff --git a/ios/chrome/browser/web/web_state_delegate_browser_agent.mm b/ios/chrome/browser/web/web_state_delegate_browser_agent.mm index cb0425c..c8900bfc 100644 --- a/ios/chrome/browser/web/web_state_delegate_browser_agent.mm +++ b/ios/chrome/browser/web/web_state_delegate_browser_agent.mm
@@ -11,10 +11,9 @@ #import "ios/chrome/browser/overlays/public/overlay_request_queue.h" #import "ios/chrome/browser/overlays/public/overlay_response.h" #import "ios/chrome/browser/overlays/public/web_content_area/http_auth_overlay.h" -#import "ios/chrome/browser/ui/dialogs/nsurl_protection_space_util.h" - #import "ios/chrome/browser/snapshots/snapshot_tab_helper.h" #import "ios/chrome/browser/ui/context_menu/context_menu_configuration_provider.h" +#import "ios/chrome/browser/ui/dialogs/nsurl_protection_space_util.h" #import "ios/chrome/browser/url_loading/url_loading_browser_agent.h" #import "ios/chrome/browser/url_loading/url_loading_params.h" #import "ios/chrome/browser/web/blocked_popup_tab_helper.h"
diff --git a/ios/chrome/browser/web_state_list/DEPS b/ios/chrome/browser/web_state_list/DEPS new file mode 100644 index 0000000..841d4f60 --- /dev/null +++ b/ios/chrome/browser/web_state_list/DEPS
@@ -0,0 +1,7 @@ +specific_include_rules = { + # TODO(crbug.com/1294160): Remove this dependency. + "^web_state_list_metrics_browser_agent.mm": [ + "+ios/chrome/browser/ui/util/uikit_ui_util.h", + ], +} +
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 index cc72902..74ddd10 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -5323b8723f4bfb6e4ac4cfa71362d3876d89b347 \ No newline at end of file +550a19845deb3b707863e3aa87c2fc569fdc16f5 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 index 0829d36..cff9048 100644 --- a/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -10ee10a4126e91957a994c27c751b3027dc57cbd \ No newline at end of file +0070d3c6a25e497510bef6d2bb004f341a8c9638 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 index 43e48a3..53bed98 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -24ff8abdae794bddf80b9eaf58827eb15a93f900 \ No newline at end of file +2de6686b4af5196815dac9c0d22fd948b10ecefb \ No newline at end of file
diff --git a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 index 98024c8b..0ff9be6 100644 --- a/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/chrome_sso_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -29291014b09800078bc8097debaf88a3d5f496ea \ No newline at end of file +d9cc618b0b3cff4427b6c6e8e4e5020235ac20c4 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 index a9d82f57..c9c18cf 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -70b426fd753738dbd992009246cc6d8d8d29ff0a \ No newline at end of file +a6ca90c01ec8ffd5b96f4e35897252233093853c \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 index 608869e..6118bc5 100644 --- a/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_dogfood_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -fcc0e34cb93055250840d6e29bc732b184a8c402 \ No newline at end of file +2199bab05492b24981cc131506c891be85c1e13c \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 index ed6fe4ef..1028a27f 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -376827318d7d8ce8f1f0abf986e4af3e33336085 \ No newline at end of file +e46d3b78a0ac1f467a8a499a3091c9fc03a022c2 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 index 0dd4a15d..15722ae1 100644 --- a/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/remoting_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -bba6a112fe50d780d93dc989572004d0d01fb19f \ No newline at end of file +df1a9e0de72c3969bdcf7abeed228bcdd6368899 \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 index 34950f8..23865222 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.ios.zip.sha1
@@ -1 +1 @@ -45f6098b0dcaf04d45e3983c0ea9a3016b0a16f8 \ No newline at end of file +54dc4f15b37326971bb377b45fb9271eb110871f \ No newline at end of file
diff --git a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 index 071a987..4de1eda 100644 --- a/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1 +++ b/ios/google_internal/frameworks/web_view_shell_internal_dynamic_framework.iossimulator.zip.sha1
@@ -1 +1 @@ -15531cf827b6532f1640b0913d5c5ce5e99c88fc \ No newline at end of file +cbb57317d39b4dccf0d9ccb3d1a79994ad5a0cb6 \ No newline at end of file
diff --git a/ios/web/web_state/ui/crw_web_controller.mm b/ios/web/web_state/ui/crw_web_controller.mm index 3a38393..05788fe 100644 --- a/ios/web/web_state/ui/crw_web_controller.mm +++ b/ios/web/web_state/ui/crw_web_controller.mm
@@ -1274,19 +1274,6 @@ - (void)webViewScrollViewDidZoom: (CRWWebViewScrollViewProxy*)webViewScrollViewProxy { _pageHasZoomed = YES; - - __weak UIScrollView* weakScrollView = self.webScrollView; - [self extractViewportTagWithCompletion:^( - const web::PageViewportState* viewportState) { - if (!weakScrollView) - return; - UIScrollView* scrollView = weakScrollView; - if (viewportState && !viewportState->viewport_tag_present() && - [scrollView minimumZoomScale] == [scrollView maximumZoomScale] && - [scrollView zoomScale] > 1.0) { - UMA_HISTOGRAM_BOOLEAN("Renderer.ViewportZoomBugCount", true); - } - }]; } - (void)webViewScrollViewDidResetContentSize:
diff --git a/media/base/key_system_properties.h b/media/base/key_system_properties.h index bd2bab2..6eeb877 100644 --- a/media/base/key_system_properties.h +++ b/media/base/key_system_properties.h
@@ -7,6 +7,7 @@ #include <string> +#include "base/callback.h" #include "build/build_config.h" #include "media/base/decrypt_config.h" #include "media/base/eme_constants.h" @@ -77,6 +78,12 @@ virtual bool UseAesDecryptor() const; }; +using KeySystemPropertiesVector = + std::vector<std::unique_ptr<KeySystemProperties>>; + +using GetSupportedKeySystemsCB = + base::OnceCallback<void(KeySystemPropertiesVector)>; + } // namespace media #endif // MEDIA_BASE_KEY_SYSTEM_PROPERTIES_H_
diff --git a/media/base/key_systems.cc b/media/base/key_systems.cc index 872f3b0..adf33338 100644 --- a/media/base/key_systems.cc +++ b/media/base/key_systems.cc
@@ -9,8 +9,11 @@ #include <memory> #include <unordered_map> +#include "base/callback_helpers.h" +#include "base/callback_list.h" #include "base/cxx17_backports.h" #include "base/logging.h" +#include "base/memory/weak_ptr.h" #include "base/no_destructor.h" #include "base/notreached.h" #include "base/strings/string_util.h" @@ -238,6 +241,32 @@ base::CompareCase::SENSITIVE); } +// Returns whether distinctive identifiers and persistent state can be reliably +// blocked for |properties| (and therefore be safely configurable). +static bool CanBlock(const KeySystemProperties& properties) { + // When AesDecryptor is used, we are sure we can block. + if (properties.UseAesDecryptor()) + return true; + + // For External Clear Key, it is either implemented as a library CDM (Clear + // Key CDM), which is covered above, or by using AesDecryptor remotely, e.g. + // via MojoCdm. In both cases, we can block. This is only used for testing. + if (base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting) && + IsExternalClearKey(properties.GetBaseKeySystemName())) + return true; + +#if BUILDFLAG(ENABLE_LIBRARY_CDMS) + // When library CDMs are enabled, we are either using AesDecryptor, or using + // the library CDM hosted in a sandboxed process. In both cases distinctive + // identifiers and persistent state can be reliably blocked. + return true; +#else + // For other platforms assume the CDM can and will do anything. So we cannot + // block. + return false; +#endif +} + class KeySystemsImpl : public KeySystems { public: static KeySystemsImpl* GetInstance(); @@ -245,15 +274,9 @@ KeySystemsImpl(const KeySystemsImpl&) = delete; KeySystemsImpl& operator=(const KeySystemsImpl&) = delete; - // These two functions are for testing purpose only. - void AddCodecMaskForTesting(EmeMediaType media_type, - const std::string& codec, - uint32_t mask); - void AddMimeTypeCodecMaskForTesting(const std::string& mime_type, - uint32_t mask); - // Implementation of KeySystems interface. - void UpdateIfNeeded() override; + void UpdateIfNeeded(base::OnceClosure done_cb) override; + bool IsUpToDate() override; std::string GetBaseKeySystemName( const std::string& key_system) const override; bool IsSupportedKeySystem(const std::string& key_system) const override; @@ -281,18 +304,29 @@ EmeFeatureSupport GetDistinctiveIdentifierSupport( const std::string& key_system) const override; + // These two functions are for testing purpose only. + void AddCodecMaskForTesting(EmeMediaType media_type, + const std::string& codec, + uint32_t mask); + void AddMimeTypeCodecMaskForTesting(const std::string& mime_type, + uint32_t mask); + private: friend class base::NoDestructor<KeySystemsImpl>; + using KeySystemPropertiesMap = + std::unordered_map<std::string, std::unique_ptr<KeySystemProperties>>; + using MimeTypeToCodecsMap = std::unordered_map<std::string, SupportedCodecs>; + using CodecMap = std::unordered_map<std::string, EmeCodec>; + using InitDataTypesMap = std::unordered_map<std::string, EmeInitDataType>; + KeySystemsImpl(); ~KeySystemsImpl() override; - void InitializeUMAInfo(); - + bool IsUpdateNeeded(); void UpdateSupportedKeySystems(); - - void AddSupportedKeySystems( - std::vector<std::unique_ptr<KeySystemProperties>> key_systems); + void OnSupportedKeySystemsUpdated(KeySystemPropertiesVector key_systems); + void ProcessSupportedKeySystems(KeySystemPropertiesVector key_systems); const KeySystemProperties* GetKeySystemProperties( const std::string& key_system) const; @@ -301,12 +335,6 @@ bool IsValidMimeTypeCodecsCombination(const std::string& mime_type, SupportedCodecs codecs) const; - using KeySystemPropertiesMap = - std::unordered_map<std::string, std::unique_ptr<KeySystemProperties>>; - using MimeTypeToCodecsMap = std::unordered_map<std::string, SupportedCodecs>; - using CodecMap = std::unordered_map<std::string, EmeCodec>; - using InitDataTypesMap = std::unordered_map<std::string, EmeInitDataType>; - // TODO(crbug.com/417440): Separate container enum from codec mask value. // Potentially pass EmeMediaType and a container enum. SupportedCodecs GetCodecMaskForMimeType( @@ -318,6 +346,12 @@ const std::string& container_mime_type, const std::string& codec_string) const; + // Whether the supported key systems are still up to date. + bool is_updating_ = false; + + // Pending callbacks for UpdateIfNeeded() calls. + base::OnceClosureList update_callbacks_; + // Map from key system string to KeySystemProperties instance. KeySystemPropertiesMap key_system_properties_map_; @@ -327,34 +361,69 @@ // For unit test only. CodecMap codec_map_for_testing_; - SupportedCodecs audio_codec_mask_; - SupportedCodecs video_codec_mask_; + SupportedCodecs audio_codec_mask_ = EME_CODEC_AUDIO_ALL; + SupportedCodecs video_codec_mask_ = EME_CODEC_VIDEO_ALL; // Makes sure all methods are called from the same thread. base::ThreadChecker thread_checker_; + + base::WeakPtrFactory<KeySystemsImpl> weak_factory_{this}; }; KeySystemsImpl* KeySystemsImpl::GetInstance() { static base::NoDestructor<KeySystemsImpl> key_systems; - key_systems->UpdateIfNeeded(); return key_systems.get(); } -// Because we use a thread-safe static, the key systems info must be populated -// when the instance is constructed. -KeySystemsImpl::KeySystemsImpl() - : audio_codec_mask_(EME_CODEC_AUDIO_ALL), - video_codec_mask_(EME_CODEC_VIDEO_ALL) { - for (size_t i = 0; i < base::size(kMimeTypeToCodecsMap); ++i) { - RegisterMimeType(kMimeTypeToCodecsMap[i].mime_type, - kMimeTypeToCodecsMap[i].codecs); - } +KeySystemsImpl::KeySystemsImpl() { + for (const auto& entry : kMimeTypeToCodecsMap) + RegisterMimeType(entry.mime_type, entry.codecs); - // Always update supported key systems during construction. UpdateSupportedKeySystems(); } -KeySystemsImpl::~KeySystemsImpl() = default; +KeySystemsImpl::~KeySystemsImpl() { + if (!update_callbacks_.empty()) + update_callbacks_.Notify(); +} + +bool KeySystemsImpl::IsUpdateNeeded() { + return GetMediaClient() && GetMediaClient()->IsKeySystemsUpdateNeeded(); +} + +void KeySystemsImpl::UpdateSupportedKeySystems() { + DCHECK(!is_updating_); + is_updating_ = true; + + if (!GetMediaClient()) { + OnSupportedKeySystemsUpdated({}); + return; + } + + GetMediaClient()->GetSupportedKeySystems( + base::BindOnce(&KeySystemsImpl::OnSupportedKeySystemsUpdated, + weak_factory_.GetWeakPtr())); +} + +void KeySystemsImpl::UpdateIfNeeded(base::OnceClosure done_cb) { + if (is_updating_) { + update_callbacks_.AddUnsafe(std::move(done_cb)); + return; + } + + DCHECK(update_callbacks_.empty()); + if (!IsUpdateNeeded()) { + std::move(done_cb).Run(); + return; + } + + update_callbacks_.AddUnsafe(std::move(done_cb)); + UpdateSupportedKeySystems(); +} + +bool KeySystemsImpl::IsUpToDate() { + return !is_updating_ && !IsUpdateNeeded(); +} SupportedCodecs KeySystemsImpl::GetCodecMaskForMimeType( const std::string& container_mime_type) const { @@ -410,60 +479,27 @@ return ToVideoEmeCodec(video_codec, profile); } -void KeySystemsImpl::UpdateIfNeeded() { - if (GetMediaClient() && GetMediaClient()->IsKeySystemsUpdateNeeded()) - UpdateSupportedKeySystems(); -} +void KeySystemsImpl::OnSupportedKeySystemsUpdated( + KeySystemPropertiesVector key_systems) { + DVLOG(1) << __func__; -void KeySystemsImpl::UpdateSupportedKeySystems() { - DCHECK(thread_checker_.CalledOnValidThread()); - key_system_properties_map_.clear(); - - std::vector<std::unique_ptr<KeySystemProperties>> key_systems_properties; - - // Add key systems supported by the MediaClient implementation. - if (GetMediaClient()) { - GetMediaClient()->AddSupportedKeySystems(&key_systems_properties); - } else { - DVLOG(1) << __func__ << " No media client to provide key systems"; - } + DCHECK(is_updating_); + is_updating_ = false; // Clear Key is always supported. - key_systems_properties.emplace_back(new ClearKeyProperties()); + key_systems.emplace_back(new ClearKeyProperties()); - AddSupportedKeySystems(std::move(key_systems_properties)); + ProcessSupportedKeySystems(std::move(key_systems)); + + update_callbacks_.Notify(); } -// Returns whether distinctive identifiers and persistent state can be reliably -// blocked for |properties| (and therefore be safely configurable). -static bool CanBlock(const KeySystemProperties& properties) { - // When AesDecryptor is used, we are sure we can block. - if (properties.UseAesDecryptor()) - return true; - - // For External Clear Key, it is either implemented as a library CDM (Clear - // Key CDM), which is covered above, or by using AesDecryptor remotely, e.g. - // via MojoCdm. In both cases, we can block. This is only used for testing. - if (base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting) && - IsExternalClearKey(properties.GetBaseKeySystemName())) - return true; - -#if BUILDFLAG(ENABLE_LIBRARY_CDMS) - // When library CDMs are enabled, we are either using AesDecryptor, or using - // the library CDM hosted in a sandboxed process. In both cases distinctive - // identifiers and persistent state can be reliably blocked. - return true; -#else - // For other platforms assume the CDM can and will do anything. So we cannot - // block. - return false; -#endif -} - -void KeySystemsImpl::AddSupportedKeySystems( - std::vector<std::unique_ptr<KeySystemProperties>> key_systems) { +void KeySystemsImpl::ProcessSupportedKeySystems( + KeySystemPropertiesVector key_systems) { DCHECK(thread_checker_.CalledOnValidThread()); - DCHECK(key_system_properties_map_.empty()); + + // Clear `key_system_properties_map_` before we repopulating it. + key_system_properties_map_.clear(); for (auto& properties : key_systems) { DCHECK(!properties->GetBaseKeySystemName().empty()); @@ -507,7 +543,7 @@ const auto base_key_system_name = properties->GetBaseKeySystemName(); DCHECK(!key_system_properties_map_.count(base_key_system_name)) << "Key system '" << base_key_system_name << "' already registered"; - DVLOG(1) << __func__ << ": Adding key system:" << base_key_system_name; + DVLOG(1) << __func__ << ": Adding key system " << base_key_system_name; key_system_properties_map_[base_key_system_name] = std::move(properties); } } @@ -606,6 +642,8 @@ std::string KeySystemsImpl::GetBaseKeySystemName( const std::string& key_system) const { + DCHECK(thread_checker_.CalledOnValidThread()); + const auto* properties = GetKeySystemProperties(key_system); if (!properties) { NOTREACHED() << "Key system support should have been checked";
diff --git a/media/base/key_systems.h b/media/base/key_systems.h index 494edf9..b13bf6d 100644 --- a/media/base/key_systems.h +++ b/media/base/key_systems.h
@@ -10,6 +10,7 @@ #include <string> #include <vector> +#include "base/callback.h" #include "media/base/decrypt_config.h" #include "media/base/eme_constants.h" #include "media/base/media_export.h" @@ -27,10 +28,15 @@ // |key_system| to every method. http://crbug.com/457438 class MEDIA_EXPORT KeySystems { public: + // Returns the KeySystems singleton which may or may not be updated yet. static KeySystems* GetInstance(); - // Refreshes the list of available key systems if it may be out of date. - virtual void UpdateIfNeeded() = 0; + // Updates the list of available key systems if it's not initialized or may be + // out of date. Calls the `done_cb` when done. + virtual void UpdateIfNeeded(base::OnceClosure done_cb) = 0; + + // Whether the list of available key systems is up to date. + virtual bool IsUpToDate() = 0; // Gets the base key system name, e.g. "org.chromium.foo". virtual std::string GetBaseKeySystemName(
diff --git a/media/base/key_systems_unittest.cc b/media/base/key_systems_unittest.cc index 40dc47f..cd4b792 100644 --- a/media/base/key_systems_unittest.cc +++ b/media/base/key_systems_unittest.cc
@@ -14,6 +14,7 @@ #include "base/check.h" #include "base/notreached.h" +#include "base/test/task_environment.h" #include "build/build_config.h" #include "media/base/audio_parameters.h" #include "media/base/decrypt_config.h" @@ -247,14 +248,13 @@ // MediaClient implementation. bool IsKeySystemsUpdateNeeded() final; - void AddSupportedKeySystems(std::vector<std::unique_ptr<KeySystemProperties>>* - key_systems_properties) override; + void GetSupportedKeySystems(GetSupportedKeySystemsCB cb) 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 - // after AddSupportedKeySystems() is called. + // after GetSupportedKeySystems() is called. void SetKeySystemsUpdateNeeded(); // Helper function to disable "kExternal" key system support so that we can @@ -265,29 +265,28 @@ GetAudioRendererAlgorithmParameters(AudioParameters audio_parameters) final; private: - bool is_update_needed_; - bool supports_external_key_system_; + bool is_update_needed_ = true; + bool supports_external_key_system_ = true; }; -TestMediaClient::TestMediaClient() - : is_update_needed_(true), supports_external_key_system_(true) {} - +TestMediaClient::TestMediaClient() = default; TestMediaClient::~TestMediaClient() = default; bool TestMediaClient::IsKeySystemsUpdateNeeded() { return is_update_needed_; } -void TestMediaClient::AddSupportedKeySystems( - std::vector<std::unique_ptr<KeySystemProperties>>* key_systems) { +void TestMediaClient::GetSupportedKeySystems(GetSupportedKeySystemsCB cb) { DCHECK(is_update_needed_); + KeySystemPropertiesVector key_systems; - key_systems->emplace_back(new AesKeySystemProperties(kUsesAes)); + key_systems.emplace_back(new AesKeySystemProperties(kUsesAes)); if (supports_external_key_system_) - key_systems->emplace_back(new ExternalKeySystemProperties()); + key_systems.emplace_back(new ExternalKeySystemProperties()); is_update_needed_ = false; + std::move(cb).Run(std::move(key_systems)); } bool TestMediaClient::IsSupportedAudioType(const media::AudioType& type) { @@ -360,7 +359,14 @@ SetMediaClient(&test_media_client_); } - void SetUp() override { AddContainerAndCodecMasksForTest(); } + void SetUp() override { + AddContainerAndCodecMasksForTest(); + + base::RunLoop run_loop; + KeySystems::GetInstance()->UpdateIfNeeded(run_loop.QuitClosure()); + run_loop.Run(); + ASSERT_TRUE(KeySystems::GetInstance()->IsUpToDate()); + } ~KeySystemsTest() override { // Clear the use of |test_media_client_|, which was set in SetUp(). @@ -372,6 +378,11 @@ void UpdateClientKeySystems() { test_media_client_.SetKeySystemsUpdateNeeded(); test_media_client_.DisableExternalKeySystemSupport(); + + base::RunLoop run_loop; + KeySystems::GetInstance()->UpdateIfNeeded(run_loop.QuitClosure()); + run_loop.Run(); + ASSERT_TRUE(KeySystems::GetInstance()->IsUpToDate()); } typedef std::vector<std::string> CodecVector; @@ -410,6 +421,8 @@ const CodecVector& mixed_codecs() const { return mixed_codecs_; } private: + base::test::TaskEnvironment task_environment_; + const CodecVector no_codecs_; CodecVector vp8_codec_; CodecVector vp80_codec_;
diff --git a/media/base/media_client.h b/media/base/media_client.h index 8931490..7fc3ddf 100644 --- a/media/base/media_client.h +++ b/media/base/media_client.h
@@ -41,12 +41,11 @@ virtual ~MediaClient(); // Adds properties for supported key systems. - virtual void AddSupportedKeySystems( - std::vector<std::unique_ptr<KeySystemProperties>>* key_systems) = 0; + virtual void GetSupportedKeySystems(GetSupportedKeySystemsCB cb) = 0; // Returns whether client key systems properties should be updated. - // TODO(chcunningham): Refactor this to a proper change "observer" API that is - // less fragile (don't assume AddSupportedKeySystems has just one caller). + // TODO(xhwang): Refactor this to a proper change "observer" API that is + // less fragile (don't assume GetSupportedKeySystems has just one caller). virtual bool IsKeySystemsUpdateNeeded() = 0; // Returns true if the given audio config is supported.
diff --git a/media/base/mock_filters.h b/media/base/mock_filters.h index 1649ba3e..dbc853c 100644 --- a/media/base/mock_filters.h +++ b/media/base/mock_filters.h
@@ -857,9 +857,7 @@ ~MockMediaClient() override; // MediaClient implementation. - MOCK_METHOD1(AddSupportedKeySystems, - void(std::vector<std::unique_ptr<media::KeySystemProperties>>* - key_systems)); + MOCK_METHOD1(GetSupportedKeySystems, void(GetSupportedKeySystemsCB cb)); MOCK_METHOD0(IsKeySystemsUpdateNeeded, bool()); MOCK_METHOD1(IsSupportedAudioType, bool(const media::AudioType& type)); MOCK_METHOD1(IsSupportedVideoType, bool(const media::VideoType& type));
diff --git a/media/base/stream_parser_buffer.h b/media/base/stream_parser_buffer.h index fd994e9..b37eec6 100644 --- a/media/base/stream_parser_buffer.h +++ b/media/base/stream_parser_buffer.h
@@ -8,6 +8,7 @@ #include <stddef.h> #include <stdint.h> +#include "base/time/time.h" #include "media/base/decoder_buffer.h" #include "media/base/demuxer_stream.h" #include "media/base/media_export.h" @@ -95,6 +96,8 @@ constexpr int64_t InMilliseconds() const { return ts_.InMilliseconds(); } constexpr int64_t InMicroseconds() const { return ts_.InMicroseconds(); } + constexpr bool is_inf() const { return ts_.is_inf(); } + // TODO(acolwell): Remove once all the hacks are gone. This method is called // by hacks where a decode time is being used as a presentation time. constexpr base::TimeDelta ToPresentationTime() const { return ts_; } @@ -106,6 +109,11 @@ base::TimeDelta ts_; }; +// Assert assumptions necessary for DecodeTimestamp analogues of +// base::TimeDelta::is_inf(), media::kNoTimestamp and media::kInfiniteDuration. +static_assert(kNoTimestamp.is_min() && kNoTimestamp.is_inf()); +static_assert(kInfiniteDuration.is_max() && kInfiniteDuration.is_inf()); + // Indicates an invalid or missing decode timestamp. constexpr DecodeTimestamp kNoDecodeTimestamp = DecodeTimestamp::FromPresentationTime(kNoTimestamp);
diff --git a/media/base/test_helpers.h b/media/base/test_helpers.h index 6d98c81f..1b4b0c6 100644 --- a/media/base/test_helpers.h +++ b/media/base/test_helpers.h
@@ -517,12 +517,23 @@ base::NumberToString(next_pts_us) + "us"); } +MATCHER_P(PtsUnknown, frame_type, "") { + return CONTAINS_STRING( + arg, "Unknown PTS for " + std::string(frame_type) + " frame"); +} + MATCHER_P2(FrameDurationUnknown, frame_type, pts_us, "") { return CONTAINS_STRING(arg, "Unknown duration for " + std::string(frame_type) + " frame at PTS " + base::NumberToString(pts_us) + "us"); } +MATCHER_P3(FrameTimeOutOfRange, when, pts_or_dts, frame_type, "") { + return CONTAINS_STRING( + arg, std::string(when) + ", " + pts_or_dts + " for " + frame_type + + " frame exceeds range allowed by implementation"); +} + } // namespace media #endif // MEDIA_BASE_TEST_HELPERS_H_
diff --git a/media/cdm/BUILD.gn b/media/cdm/BUILD.gn index e67c655..0fa04f87 100644 --- a/media/cdm/BUILD.gn +++ b/media/cdm/BUILD.gn
@@ -84,7 +84,6 @@ deps += [ ":cdm_api", ":cdm_paths", - "//components/crash/core/common:crash_key", ] sources += [ "cdm_adapter.cc", @@ -122,6 +121,7 @@ deps += [ ":cdm_api", ":cdm_type_conversion", + "//components/crash/core/common:crash_key", ] }
diff --git a/media/cdm/default_cdm_factory.cc b/media/cdm/default_cdm_factory.cc index f6f9d0e..6e5cfc5 100644 --- a/media/cdm/default_cdm_factory.cc +++ b/media/cdm/default_cdm_factory.cc
@@ -12,7 +12,6 @@ #include "media/base/cdm_config.h" #include "media/base/content_decryption_module.h" #include "media/base/key_system_names.h" -#include "media/base/key_systems.h" #include "media/base/media_switches.h" #include "media/cdm/aes_decryptor.h" #include "url/origin.h" @@ -24,7 +23,7 @@ DefaultCdmFactory::~DefaultCdmFactory() = default; static bool ShouldCreateAesDecryptor(const std::string& key_system) { - if (CanUseAesDecryptor(key_system)) + if (IsClearKey(key_system)) return true; // Should create AesDecryptor to support External Clear Key key system.
diff --git a/media/filters/frame_processor.cc b/media/filters/frame_processor.cc index 4e7f622e6..9178624 100644 --- a/media/filters/frame_processor.cc +++ b/media/filters/frame_processor.cc
@@ -810,6 +810,22 @@ // and failed processing. DCHECK(decode_timestamp != kNoDecodeTimestamp); + if (presentation_timestamp.is_inf()) { + MEDIA_LOG(ERROR, media_log_) + << "Before adjusting by timestampOffset, PTS for " + << frame->GetTypeName() + << " frame exceeds range allowed by implementation"; + return false; + } + + if (decode_timestamp.is_inf()) { + MEDIA_LOG(ERROR, media_log_) + << "Before adjusting by timestampOffset, DTS for " + << frame->GetTypeName() + << " frame exceeds range allowed by implementation"; + return false; + } + // TODO(wolenetz): Determine whether any DTS>PTS logging is needed. See // http://crbug.com/354518. DVLOG_IF(2, decode_timestamp.ToPresentationTime() > presentation_timestamp)
diff --git a/media/filters/frame_processor_unittest.cc b/media/filters/frame_processor_unittest.cc index 2157918..279a9d7 100644 --- a/media/filters/frame_processor_unittest.cc +++ b/media/filters/frame_processor_unittest.cc
@@ -5,6 +5,7 @@ #include <stddef.h> #include <stdint.h> +#include <cstring> #include <map> #include <memory> #include <string> @@ -27,6 +28,7 @@ #include "media/filters/frame_processor.h" #include "testing/gtest/include/gtest/gtest.h" +using base::Milliseconds; using ::testing::_; using ::testing::InSequence; using ::testing::StrictMock; @@ -34,10 +36,19 @@ namespace { -// Helper to shorten "base::Milliseconds(...)" in these test -// cases for integer milliseconds. -constexpr base::TimeDelta Milliseconds(int64_t milliseconds) { - return base::Milliseconds(milliseconds); +// Helpers to encode/decode a base::TimeDelta to/from a string, used in these +// tests to populate coded frame payloads with an encoded version of the +// original frame timestamp while (slightly) obfuscating the payload itself to +// help ensure the payload itself is neither changed by frame processing nor +// interpreted directly and mistakenly as a base::TimeDelta by frame processing. +std::string EncodeTestPayload(base::TimeDelta timestamp) { + return base::NumberToString(timestamp.InMicroseconds()); +} + +base::TimeDelta DecodeTestPayload(std::string payload) { + int64_t microseconds = 0; + CHECK(base::StringToInt64(payload, µseconds)); + return base::Microseconds(microseconds); } } // namespace @@ -141,6 +152,20 @@ frame_processor_->SetGroupStartTimestampIfInSequenceMode(timestamp_offset_); } + base::TimeDelta MillisecondStringToTimestamp(std::string ts_string) { + if (ts_string == "Min") { + return kNoTimestamp; + } + + if (ts_string == "Max") { + return kInfiniteDuration; + } + + double ts_double; + CHECK(base::StringToDouble(ts_string, &ts_double)); + return base::Milliseconds(ts_double); + } + BufferQueue StringToBufferQueue(const std::string& buffers_to_append, const TrackId track_id, const DemuxerStream::Type type) { @@ -163,22 +188,26 @@ buffer_timestamps.push_back(buffer_timestamps[0]); CHECK_EQ(2u, buffer_timestamps.size()); - double time_in_ms, decode_time_in_ms; - CHECK(base::StringToDouble(buffer_timestamps[0], &time_in_ms)); - CHECK(base::StringToDouble(buffer_timestamps[1], &decode_time_in_ms)); + const base::TimeDelta pts = + MillisecondStringToTimestamp(buffer_timestamps[0]); + const DecodeTimestamp dts = DecodeTimestamp::FromPresentationTime( + MillisecondStringToTimestamp(buffer_timestamps[1])); - // Create buffer. Encode the original time_in_ms as the buffer's data to - // enable later verification of possible buffer relocation in presentation + // Create buffer. Encode the original pts as the buffer's data to enable + // later verification of possible buffer relocation in presentation // timeline due to coded frame processing. - const uint8_t* timestamp_as_data = - reinterpret_cast<uint8_t*>(&time_in_ms); - scoped_refptr<StreamParserBuffer> buffer = - StreamParserBuffer::CopyFrom(timestamp_as_data, sizeof(time_in_ms), - is_keyframe, type, track_id); - buffer->set_timestamp(base::Milliseconds(time_in_ms)); - if (time_in_ms != decode_time_in_ms) { - buffer->SetDecodeTimestamp(DecodeTimestamp::FromPresentationTime( - base::Milliseconds(decode_time_in_ms))); + const std::string payload_string = EncodeTestPayload(pts); + const char* pts_as_cstr = payload_string.c_str(); + scoped_refptr<StreamParserBuffer> buffer = StreamParserBuffer::CopyFrom( + reinterpret_cast<const uint8_t*>(pts_as_cstr), strlen(pts_as_cstr), + is_keyframe, type, track_id); + CHECK(DecodeTestPayload( + std::string(reinterpret_cast<const char*>(buffer->data()), + buffer->data_size())) == pts); + + buffer->set_timestamp(pts); + if (DecodeTimestamp::FromPresentationTime(pts) != dts) { + buffer->SetDecodeTimestamp(dts); } buffer->set_duration(frame_duration_); @@ -298,9 +327,11 @@ // Decode the original_time_in_ms from the buffer's data. double original_time_in_ms; - ASSERT_EQ(sizeof(original_time_in_ms), last_read_buffer_->data_size()); - original_time_in_ms = *(reinterpret_cast<const double*>( - last_read_buffer_->data())); + original_time_in_ms = + DecodeTestPayload(std::string(reinterpret_cast<const char*>( + last_read_buffer_->data()), + last_read_buffer_->data_size())) + .InMillisecondsF(); if (original_time_in_ms != time_in_ms) ss << ":" << original_time_in_ms; @@ -2296,7 +2327,7 @@ "0K 10N 20N 22N 32K 42N 45K"); } -TEST_P(FrameProcessorTest, FrameDuration_kNoTimestamp_FailsParse) { +TEST_P(FrameProcessorTest, FrameDuration_kNoTimestamp_Fails) { InSequence s; AddTestTracks(HAS_AUDIO); frame_processor_->SetSequenceMode(use_sequence_mode_); @@ -2306,6 +2337,53 @@ EXPECT_FALSE(ProcessFrames("1K", "")); } +TEST_P(FrameProcessorTest, + Pts_BeforeTimestampOffsetApplied_kNoTimestamp_Fails) { + InSequence s; + AddTestTracks(HAS_AUDIO); + frame_processor_->SetSequenceMode(use_sequence_mode_); + + EXPECT_MEDIA_LOG(PtsUnknown("audio")); + EXPECT_FALSE(ProcessFrames("MinK", "")); +} + +TEST_P(FrameProcessorTest, + Pts_BeforeTimestampOffsetApplied_kInfiniteDuration_Fails) { + InSequence s; + AddTestTracks(HAS_AUDIO); + frame_processor_->SetSequenceMode(use_sequence_mode_); + + EXPECT_MEDIA_LOG(FrameTimeOutOfRange("Before adjusting by timestampOffset", + "PTS", "audio")); + EXPECT_FALSE(ProcessFrames("MaxK", "")); +} + +TEST_P(FrameProcessorTest, + Dts_BeforeTimestampOffsetApplied_kNoDecodeTimestamp_UsesPtsIfValid) { + InSequence s; + AddTestTracks(HAS_AUDIO); + frame_processor_->SetSequenceMode(use_sequence_mode_); + + // When PTS is valid, but DTS is kNoDecodeTimestamp, then + // StreamParserBuffer::GetDecodeTimestamp() just returns the frame's PTS. + EXPECT_CALL(callbacks_, PossibleDurationIncrease(Milliseconds(10))); + EXPECT_TRUE(ProcessFrames("0|MinK", "")); + + CheckExpectedRangesByTimestamp(audio_.get(), "{ [0,10) }"); + CheckReadsAndKeyframenessThenReadStalls(audio_.get(), "0K"); +} + +TEST_P(FrameProcessorTest, + Dts_BeforeTimestampOffsetApplied_kMaxDecodeTimestamp_Fails) { + InSequence s; + AddTestTracks(HAS_AUDIO); + frame_processor_->SetSequenceMode(use_sequence_mode_); + + EXPECT_MEDIA_LOG(FrameTimeOutOfRange("Before adjusting by timestampOffset", + "DTS", "audio")); + EXPECT_FALSE(ProcessFrames("0|MaxK", "")); +} + INSTANTIATE_TEST_SUITE_P(SequenceMode, FrameProcessorTest, Values(true)); INSTANTIATE_TEST_SUITE_P(SegmentsMode, FrameProcessorTest, Values(false));
diff --git a/media/gpu/BUILD.gn b/media/gpu/BUILD.gn index 71377faf..9f42e4e6 100644 --- a/media/gpu/BUILD.gn +++ b/media/gpu/BUILD.gn
@@ -216,6 +216,12 @@ "windows/supported_profile_helpers.cc", "windows/supported_profile_helpers.h", ] + if (enable_platform_hevc_decoding) { + sources += [ + "windows/d3d11_h265_accelerator.cc", + "windows/d3d11_h265_accelerator.h", + ] + } configs += [ "//third_party/khronos:khronos_headers" ] public_deps += [ "//media/base/win:media_foundation_util" ] deps += [
diff --git a/media/gpu/h265_dpb.cc b/media/gpu/h265_dpb.cc index f644bb2e..1a7f401 100644 --- a/media/gpu/h265_dpb.cc +++ b/media/gpu/h265_dpb.cc
@@ -20,6 +20,10 @@ return nullptr; } +D3D11H265Picture* H265Picture::AsD3D11H265Picture() { + return nullptr; +} + void H265DPB::set_max_num_pics(size_t max_num_pics) { DCHECK_LE(max_num_pics, static_cast<size_t>(kMaxDpbSize)); max_num_pics_ = max_num_pics;
diff --git a/media/gpu/h265_dpb.h b/media/gpu/h265_dpb.h index 78450ec..9d55528f 100644 --- a/media/gpu/h265_dpb.h +++ b/media/gpu/h265_dpb.h
@@ -15,6 +15,7 @@ namespace media { class VaapiH265Picture; +class D3D11H265Picture; // A picture (a frame or a field) in the H.265 spec sense. // See spec at http://www.itu.int/rec/T-REC-H.265 @@ -28,6 +29,7 @@ H265Picture& operator=(const H265Picture&) = delete; virtual VaapiH265Picture* AsVaapiH265Picture(); + virtual D3D11H265Picture* AsD3D11H265Picture(); enum ReferenceType { kUnused = 0,
diff --git a/media/gpu/v4l2/v4l2_device.cc b/media/gpu/v4l2/v4l2_device.cc index 9433566f..8caa568 100644 --- a/media/gpu/v4l2/v4l2_device.cc +++ b/media/gpu/v4l2/v4l2_device.cc
@@ -1524,6 +1524,18 @@ return nullptr; } +std::string V4L2Device::GetDriverName() { + struct v4l2_capability caps; + memset(&caps, 0, sizeof(caps)); + if (Ioctl(VIDIOC_QUERYCAP, &caps) != 0) { + VPLOGF(1) << "ioctl() failed: VIDIOC_QUERYCAP" + << ", caps check failed: 0x" << std::hex << caps.capabilities; + return ""; + } + + return std::string(reinterpret_cast<const char*>(caps.driver)); +} + // static uint32_t V4L2Device::VideoCodecProfileToV4L2PixFmt(VideoCodecProfile profile, bool slice_based) {
diff --git a/media/gpu/v4l2/v4l2_device.h b/media/gpu/v4l2/v4l2_device.h index 22ce702..70f47ae 100644 --- a/media/gpu/v4l2/v4l2_device.h +++ b/media/gpu/v4l2/v4l2_device.h
@@ -644,6 +644,9 @@ // The device will be closed in the destructor. virtual bool Open(Type type, uint32_t v4l2_pixfmt) = 0; + // Returns the driver name. + std::string GetDriverName(); + // Returns the V4L2Queue corresponding to the requested |type|, or nullptr // if the requested queue type is not supported. scoped_refptr<V4L2Queue> GetQueue(enum v4l2_buf_type type);
diff --git a/media/gpu/v4l2/v4l2_stateful_workaround.cc b/media/gpu/v4l2/v4l2_stateful_workaround.cc index 42393b7..4a1e156 100644 --- a/media/gpu/v4l2/v4l2_stateful_workaround.cc +++ b/media/gpu/v4l2/v4l2_stateful_workaround.cc
@@ -12,10 +12,8 @@ #include "base/containers/small_map.h" #include "base/containers/span.h" -#include "base/feature_list.h" #include "base/memory/ptr_util.h" #include "media/base/decoder_buffer.h" -#include "media/base/media_switches.h" #include "media/base/video_types.h" #include "media/gpu/macros.h" #include "media/parsers/vp8_parser.h" @@ -229,14 +227,8 @@ return workarounds; } -bool AppendVP9SuperFrameIndexIfNeeded(scoped_refptr<DecoderBuffer>& buffer) { - if (buffer->side_data_size() == 0) - return true; - - if (!base::FeatureList::IsEnabled(media::kVp9kSVCHWDecoding)) { - DLOG(ERROR) << "Vp9 k-SVC hardware decoding is disabled"; - return false; - } +bool AppendVP9SuperFrameIndex(scoped_refptr<DecoderBuffer>& buffer) { + DCHECK_GT(buffer->side_data_size(), 0u); const size_t num_of_layers = buffer->side_data_size() / sizeof(uint32_t); if (num_of_layers > 3u) {
diff --git a/media/gpu/v4l2/v4l2_stateful_workaround.h b/media/gpu/v4l2/v4l2_stateful_workaround.h index d01e9c9..619953c 100644 --- a/media/gpu/v4l2/v4l2_stateful_workaround.h +++ b/media/gpu/v4l2/v4l2_stateful_workaround.h
@@ -6,6 +6,7 @@ #define MEDIA_GPU_V4L2_V4L2_STATEFUL_WORKAROUND_H_ #include <memory> +#include <string> #include <vector> #include "media/base/video_types.h" @@ -40,13 +41,13 @@ VideoCodecProfile profile); // DecoderBuffer contains superframe in VP9 k-SVC stream but doesn't have -// superframe_index. If DecoderBuffer has side_data, it stands for sizes of -// frames in a superframe, this constructs superframe_index from them. +// superframe_index. This constructs superframe_index from side_data of +// DecoderBuffer which stands for sizes of frames in a superframe. // |buffer| is replaced with a new DecoderBuffer, where superframe index is // appended to |buffer| data. Besides, show_frame in the new DecoderBuffer is // overwritten so that show_frame is one only in the top spatial layer. // See go/VP9-k-SVC-Decoing-VAAPI for detail. -bool AppendVP9SuperFrameIndexIfNeeded(scoped_refptr<DecoderBuffer>& buffer); +bool AppendVP9SuperFrameIndex(scoped_refptr<DecoderBuffer>& buffer); } // namespace media #endif // MEDIA_GPU_V4L2_V4L2_STATEFUL_WORKAROUND_H_
diff --git a/media/gpu/v4l2/v4l2_stateful_workaround_unittest.cc b/media/gpu/v4l2/v4l2_stateful_workaround_unittest.cc index ebe13ce..303a00f 100644 --- a/media/gpu/v4l2/v4l2_stateful_workaround_unittest.cc +++ b/media/gpu/v4l2/v4l2_stateful_workaround_unittest.cc
@@ -63,7 +63,7 @@ DecoderBuffer::CopyFrom(tmp_buffer.data(), tmp_buffer.size()); AppendSideData(*decoder_buffer, frame_sizes); - AppendVP9SuperFrameIndexIfNeeded(decoder_buffer); + AppendVP9SuperFrameIndex(decoder_buffer); if (frame_sizes.size() == 1) { EXPECT_EQ(decoder_buffer->data_size(), buffer_size); continue; @@ -110,7 +110,7 @@ DecoderBuffer::CopyFrom(merged_buffer.data(), merged_buffer.size()); AppendSideData(*decoder_buffer, frame_sizes); - AppendVP9SuperFrameIndexIfNeeded(decoder_buffer); + AppendVP9SuperFrameIndex(decoder_buffer); Vp9Parser vp9_parser(/*parsing_compressed_header=*/false); vp9_parser.SetStream(decoder_buffer->data(), decoder_buffer->data_size(),
diff --git a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc index 06fda6d6..ccb8296e 100644 --- a/media/gpu/v4l2/v4l2_video_decode_accelerator.cc +++ b/media/gpu/v4l2/v4l2_video_decode_accelerator.cc
@@ -73,6 +73,16 @@ namespace media { +namespace { + +bool IsVp9KSVCStream(uint32_t input_format_fourcc, + const DecoderBuffer& decoder_buffer) { + return input_format_fourcc == V4L2_PIX_FMT_VP9 && + decoder_buffer.side_data_size() > 0; +} + +} // namespace + // static const uint32_t V4L2VideoDecodeAccelerator::supported_input_fourccs_[] = { V4L2_PIX_FMT_H264, V4L2_PIX_FMT_VP8, V4L2_PIX_FMT_VP9, @@ -857,6 +867,12 @@ if (IsDestroyPending()) return; + if (IsVp9KSVCStream(input_format_fourcc_, *buffer)) { + LOG(ERROR) << "VDA does not support decoding VP9 k-SVC stream"; + NOTIFY_ERROR(PLATFORM_FAILURE); + return; + } + std::unique_ptr<BitstreamBufferRef> bitstream_record(new BitstreamBufferRef( decode_client_, decode_task_runner_, std::move(buffer), bitstream_id));
diff --git a/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc b/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc index b38034e..7b238d9 100644 --- a/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc +++ b/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.cc
@@ -11,10 +11,12 @@ #include "base/bind.h" #include "base/containers/contains.h" +#include "base/feature_list.h" #include "base/logging.h" #include "base/metrics/histogram_macros.h" #include "base/sequence_checker.h" #include "base/task/sequenced_task_runner.h" +#include "media/base/media_switches.h" #include "media/base/video_codecs.h" #include "media/gpu/chromeos/dmabuf_video_frame_pool.h" #include "media/gpu/macros.h" @@ -26,6 +28,20 @@ namespace media { +namespace { + +bool IsVp9KSVCStream(VideoCodecProfile profile, + const DecoderBuffer& decoder_buffer) { + return VideoCodecProfileToVideoCodec(profile) == VideoCodec::kVP9 && + decoder_buffer.side_data_size() > 0; +} + +bool IsVp9KSVCSupportedDriver(const std::string& driver_name) { + const std::string kVP9KSVCSupportedDrivers[] = {"qcom-venus"}; + return base::Contains(kVP9KSVCSupportedDrivers, driver_name); +} +} // namespace + V4L2StatefulVideoDecoderBackend::DecodeRequest::DecodeRequest( scoped_refptr<DecoderBuffer> buf, VideoDecoder::DecodeCB cb, @@ -51,6 +67,7 @@ const VideoColorSpace& color_space, scoped_refptr<base::SequencedTaskRunner> task_runner) : V4L2VideoDecoderBackend(client, std::move(device)), + driver_name_(device_->GetDriverName()), profile_(profile), color_space_(color_space), task_runner_(task_runner) { @@ -157,9 +174,23 @@ current_decode_request_ = std::move(decode_request); DCHECK_EQ(current_decode_request_->bytes_used, 0u); - if (VideoCodecProfileToVideoCodec(profile_) == VideoCodec::kVP9 && - !AppendVP9SuperFrameIndexIfNeeded(current_decode_request_->buffer)) { - VLOGF(1) << "Failed to append superframe index for VP9 k-SVC frame"; + if (IsVp9KSVCStream(profile_, *current_decode_request_->buffer)) { + if (!base::FeatureList::IsEnabled(media::kVp9kSVCHWDecoding)) { + DLOG(ERROR) << "Vp9 k-SVC hardware decoding is disabled"; + client_->OnBackendError(); + return; + } + if (!IsVp9KSVCSupportedDriver(driver_name_)) { + DLOG(ERROR) << driver_name_ << " doesn't support VP9 k-SVC decoding"; + client_->OnBackendError(); + return; + } + + if (!AppendVP9SuperFrameIndex(current_decode_request_->buffer)) { + LOG(ERROR) << "Failed to append superframe index for VP9 k-SVC frame"; + client_->OnBackendError(); + return; + } } }
diff --git a/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h b/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h index 169bfd0..49b5857 100644 --- a/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h +++ b/media/gpu/v4l2/v4l2_video_decoder_backend_stateful.h
@@ -6,6 +6,7 @@ #define MEDIA_GPU_V4L2_V4L2_VIDEO_DECODER_BACKEND_STATEFUL_H_ #include <memory> +#include <string> #include <vector> #include "base/containers/queue.h" @@ -118,6 +119,9 @@ // Process all the event in the event queue void ProcessEventQueue(); + // The name of the running driver. + const std::string driver_name_; + // Video profile we are decoding. VideoCodecProfile profile_;
diff --git a/media/gpu/windows/d3d11_decoder_configurator.cc b/media/gpu/windows/d3d11_decoder_configurator.cc index f88a4aee..8b7f0b5e 100644 --- a/media/gpu/windows/d3d11_decoder_configurator.cc +++ b/media/gpu/windows/d3d11_decoder_configurator.cc
@@ -63,7 +63,15 @@ decoder_guid = DXVA_ModeAV1_VLD_Profile1; } else if (config.profile() == AV1PROFILE_PROFILE_PRO) { decoder_guid = DXVA_ModeAV1_VLD_Profile2; - } else { + } +#if BUILDFLAG(ENABLE_PLATFORM_HEVC_DECODING) + else if (config.profile() == HEVCPROFILE_MAIN) { + decoder_guid = D3D11_DECODER_PROFILE_HEVC_VLD_MAIN; + } else if (config.profile() == HEVCPROFILE_MAIN10) { + decoder_guid = D3D11_DECODER_PROFILE_HEVC_VLD_MAIN10; + } +#endif + else { MEDIA_LOG(INFO, media_log) << "D3D11VideoDecoder does not support codec " << config.codec(); return nullptr;
diff --git a/media/gpu/windows/d3d11_h264_accelerator.h b/media/gpu/windows/d3d11_h264_accelerator.h index 98268fa..0f3693d 100644 --- a/media/gpu/windows/d3d11_h264_accelerator.h +++ b/media/gpu/windows/d3d11_h264_accelerator.h
@@ -67,6 +67,10 @@ void Reset() override; bool OutputPicture(scoped_refptr<H264Picture> pic) override; + private: + bool SubmitSliceData(); + bool RetrieveBitstreamBuffer(); + // Gets a pic params struct with the constant fields set. void FillPicParamsWithConstants(DXVA_PicParams_H264* pic_param); @@ -80,16 +84,12 @@ // Populate the pic params with fields from the slice header structure. void PicParamsFromSliceHeader(DXVA_PicParams_H264* pic_param, - const H264SliceHeader* pps); + const H264SliceHeader* slice_hdr); void PicParamsFromPic(DXVA_PicParams_H264* pic_param, D3D11H264Picture* pic); void SetVideoDecoder(ComD3D11VideoDecoder video_decoder); - private: - bool SubmitSliceData(); - bool RetrieveBitstreamBuffer(); - // Record a failure to DVLOG and |media_log_|. void RecordFailure(const std::string& reason, D3D11Status::Codes code,
diff --git a/media/gpu/windows/d3d11_h265_accelerator.cc b/media/gpu/windows/d3d11_h265_accelerator.cc new file mode 100644 index 0000000..4398c0f --- /dev/null +++ b/media/gpu/windows/d3d11_h265_accelerator.cc
@@ -0,0 +1,802 @@ +// Copyright 2022 The Chromium 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/gpu/windows/d3d11_h265_accelerator.h" + +#include <windows.h> + +#include <map> + +#include "base/memory/ptr_util.h" +#include "base/memory/raw_ptr.h" +#include "base/metrics/histogram_functions.h" +#include "base/ranges/algorithm.h" +#include "base/strings/string_number_conversions.h" +#include "base/trace_event/trace_event.h" +#include "media/base/media_log.h" +#include "media/base/win/mf_helpers.h" +#include "media/gpu/windows/d3d11_picture_buffer.h" +#include "media/media_buildflags.h" +#include "third_party/angle/include/EGL/egl.h" +#include "third_party/angle/include/EGL/eglext.h" +#include "ui/gfx/color_space.h" +#include "ui/gl/gl_bindings.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_image_dxgi.h" +#include "ui/gl/gl_surface_egl.h" +#include "ui/gl/scoped_binders.h" + +namespace media { + +using DecoderStatus = H265Decoder::H265Accelerator::Status; + +namespace { + +// Converts SubsampleEntry to D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK. +void AppendSubsamples( + const std::vector<SubsampleEntry>& from, + std::vector<D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK>* to) { + for (const auto& from_entry : from) { + D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK subsample = {}; + subsample.ClearSize = from_entry.clear_bytes; + subsample.EncryptedSize = from_entry.cypher_bytes; + to->push_back(subsample); + } +} + +} // namespace + +class D3D11H265Picture : public H265Picture { + public: + D3D11H265Picture(D3D11PictureBuffer* picture) + : picture(picture), picture_index_(picture->picture_index()) { + picture->set_in_picture_use(true); + } + + raw_ptr<D3D11PictureBuffer> picture; + size_t picture_index_; + + D3D11H265Picture* AsD3D11H265Picture() override { return this; } + + protected: + ~D3D11H265Picture() override; +}; + +D3D11H265Picture::~D3D11H265Picture() { + picture->set_in_picture_use(false); +} + +D3D11H265Accelerator::D3D11H265Accelerator( + D3D11VideoDecoderClient* client, + MediaLog* media_log, + ComD3D11VideoDevice video_device, + std::unique_ptr<VideoContextWrapper> video_context) + : client_(client), + media_log_(media_log), + video_device_(video_device), + video_context_(std::move(video_context)) { + DCHECK(client); + DCHECK(media_log_); + client->SetDecoderCB(base::BindRepeating( + &D3D11H265Accelerator::SetVideoDecoder, base::Unretained(this))); +} + +D3D11H265Accelerator::~D3D11H265Accelerator() {} + +scoped_refptr<H265Picture> D3D11H265Accelerator::CreateH265Picture() { + D3D11PictureBuffer* picture = client_->GetPicture(); + if (!picture) { + return nullptr; + } + return base::MakeRefCounted<D3D11H265Picture>(picture); +} + +DecoderStatus D3D11H265Accelerator::SubmitFrameMetadata( + const H265SPS* sps, + const H265PPS* pps, + const H265SliceHeader* slice_hdr, + const H265Picture::Vector& ref_pic_list, + scoped_refptr<H265Picture> pic) { + const bool is_encrypted = pic->decrypt_config(); + if (is_encrypted) { + RecordFailure("Cannot find decrypt context for the frame.", + D3D11Status::Codes::kCryptoConfigFailed); + return DecoderStatus::kFail; + } + + HRESULT hr; + for (;;) { + D3D11H265Picture* d3d11_pic = pic->AsD3D11H265Picture(); + if (!d3d11_pic) + return DecoderStatus::kFail; + + ID3D11VideoDecoderOutputView* output_view = nullptr; + auto result = d3d11_pic->picture->AcquireOutputView(); + if (result.has_value()) { + output_view = std::move(result).value(); + } else { + RecordFailure(std::move(result).error()); + return DecoderStatus::kFail; + } + + hr = video_context_->DecoderBeginFrame(video_decoder_.Get(), output_view, 0, + nullptr); + if (hr == E_PENDING || hr == D3DERR_WASSTILLDRAWING) { + base::PlatformThread::YieldCurrentThread(); + } else if (!SUCCEEDED(hr)) { + RecordFailure("DecoderBeginFrame failed", + D3D11Status::Codes::kDecoderBeginFrameFailed, hr); + return DecoderStatus::kFail; + } else { + break; + } + } + + use_scaling_lists_ = sps->scaling_list_enabled_flag; + + poc_index_into_ref_pic_list_.clear(); + for (size_t i = 0; i < media::kMaxRefPicListSize; i++) { + ref_frame_list_[i].bPicEntry = 0xFF; + ref_frame_pocs_[i] = 0; + } + + // |ref_pic_list| contains the set of pictures as described + // in HEVC spec section 8.3.2, from the lists RefPicSetLtCurr, + // RefPicSetLtFoll, RefPicSetStCurrBefore, RefPicSetStCurrAfter + // and RefPicSetStFoll. When submitting a slice, will use information + // in ref_pic_list0 and ref_pic_list1 to fill POCs of corresponding + // list in picture param. + if (ref_pic_list.size() > kMaxRefPicListSize) { + DLOG(ERROR) << "Invalid fef pic list size."; + return DecoderStatus::kFail; + } + + int i = 0; + for (auto& it : ref_pic_list) { + D3D11H265Picture* our_ref_pic = it->AsD3D11H265Picture(); + if (!our_ref_pic) + continue; + ref_frame_list_[i].Index7Bits = our_ref_pic->picture_index_; + ref_frame_list_[i].AssociatedFlag = our_ref_pic->IsLongTermRef(); + ref_frame_pocs_[i] = our_ref_pic->pic_order_cnt_val_; + poc_index_into_ref_pic_list_[our_ref_pic->pic_order_cnt_val_] = i; + i++; + } + slice_info_.clear(); + return RetrieveBitstreamBuffer() ? DecoderStatus::kOk : DecoderStatus::kFail; +} + +bool D3D11H265Accelerator::RetrieveBitstreamBuffer() { + DCHECK(!bitstream_buffer_bytes_); + DCHECK(!bitstream_buffer_size_); + + current_offset_ = 0; + void* buffer; + UINT buffer_size; + HRESULT hr = video_context_->GetDecoderBuffer( + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_BITSTREAM, &buffer_size, + &buffer); + if (!SUCCEEDED(hr)) { + RecordFailure("GetDecoderBuffer (Bitstream) failed", + D3D11Status::Codes::kGetBitstreamBufferFailed, hr); + return false; + } + bitstream_buffer_bytes_ = (uint8_t*)buffer; + bitstream_buffer_size_ = buffer_size; + + return true; +} + +void D3D11H265Accelerator::FillPicParamsWithConstants( + DXVA_PicParams_HEVC* pic) { + // According to DXVA spec section 2.2, this optional 1-bit flag + // has no meaning when used for CurrPic so always configure to 0. + pic->CurrPic.AssociatedFlag = 0; + + // num_tile_columns_minus1 and num_tile_rows_minus1 will only + // be set if tiles are enabled. Set to 0 by default. + pic->num_tile_columns_minus1 = 0; + pic->num_tile_rows_minus1 = 0; + + // Host decoder may set this to 1 if sps_max_num_reorder_pics is 0, + // but there is no requirement that NoPicReorderingFlag must be + // derived from it. So we always set it to 0 here. + pic->NoPicReorderingFlag = 0; + + // Must be set to 0 in absence of indication whether B slices are used + // or not, and it does not affect the decoding process. + pic->NoBiPredFlag = 0; + + // Shall be set to 0 and accelerators shall ignore its value. + pic->ReservedBits1 = 0; + + // Bit field added to enable DWORD alignment and should be set to 0. + pic->ReservedBits2 = 0; + + // Should always be set to 0. + pic->ReservedBits3 = 0; + + // Should be set to 0 and ignored by accelerators + pic->ReservedBits4 = 0; + + // Should always be set to 0. + pic->ReservedBits5 = 0; + + // Should always be set to 0. + pic->ReservedBits6 = 0; + + // Should always be set to 0. + pic->ReservedBits7 = 0; +} + +#define ARG_SEL(_1, _2, NAME, ...) NAME +#define SPS_TO_PP1(a) pic_param->a = sps->a; +#define SPS_TO_PP2(a, b) pic_param->a = sps->b; +#define SPS_TO_PP(...) ARG_SEL(__VA_ARGS__, SPS_TO_PP2, SPS_TO_PP1)(__VA_ARGS__) +void D3D11H265Accelerator::PicParamsFromSPS(DXVA_PicParams_HEVC* pic_param, + const H265SPS* sps) { + // Refer to formula 7-14 and 7-16 of HEVC spec. + int min_cb_log2_size_y = sps->log2_min_luma_coding_block_size_minus3 + 3; + pic_param->PicWidthInMinCbsY = + sps->pic_width_in_luma_samples >> min_cb_log2_size_y; + pic_param->PicHeightInMinCbsY = + sps->pic_height_in_luma_samples >> min_cb_log2_size_y; + // wFormatAndSequenceInfoFlags from SPS + SPS_TO_PP(chroma_format_idc); + SPS_TO_PP(separate_colour_plane_flag); + SPS_TO_PP(bit_depth_luma_minus8); + SPS_TO_PP(bit_depth_chroma_minus8); + SPS_TO_PP(log2_max_pic_order_cnt_lsb_minus4); + + // HEVC DXVA spec does not clearly state which slot + // in sps->sps_max_dec_pic_buffering_minus1 should + // be used here. However section A4.1 of HEVC spec + // requires the slot of highest tid to be used for + // indicating the maximum DPB size if level is not + // 8.5. + int highest_tid = sps->sps_max_sub_layers_minus1; + pic_param->sps_max_dec_pic_buffering_minus1 = + sps->sps_max_dec_pic_buffering_minus1[highest_tid]; + + SPS_TO_PP(log2_min_luma_coding_block_size_minus3); + SPS_TO_PP(log2_diff_max_min_luma_coding_block_size); + + // DXVA spec names them differently with HEVC spec. + SPS_TO_PP(log2_min_transform_block_size_minus2, + log2_min_luma_transform_block_size_minus2); + SPS_TO_PP(log2_diff_max_min_transform_block_size, + log2_diff_max_min_luma_transform_block_size); + + SPS_TO_PP(max_transform_hierarchy_depth_inter); + SPS_TO_PP(max_transform_hierarchy_depth_intra); + SPS_TO_PP(num_short_term_ref_pic_sets); + SPS_TO_PP(num_long_term_ref_pics_sps); + + // dwCodingParamToolFlags extracted from SPS + SPS_TO_PP(scaling_list_enabled_flag); + SPS_TO_PP(amp_enabled_flag); + SPS_TO_PP(sample_adaptive_offset_enabled_flag); + SPS_TO_PP(pcm_enabled_flag); + + if (sps->sample_adaptive_offset_enabled_flag) { + SPS_TO_PP(pcm_sample_bit_depth_luma_minus1); + SPS_TO_PP(pcm_sample_bit_depth_chroma_minus1); + SPS_TO_PP(log2_min_pcm_luma_coding_block_size_minus3); + SPS_TO_PP(log2_diff_max_min_pcm_luma_coding_block_size); + } + SPS_TO_PP(pcm_loop_filter_disabled_flag); + SPS_TO_PP(long_term_ref_pics_present_flag); + SPS_TO_PP(sps_temporal_mvp_enabled_flag); + SPS_TO_PP(strong_intra_smoothing_enabled_flag); +} +#undef SPS_TO_PP +#undef SPS_TO_PP2 +#undef SPS_TO_PP1 + +#define PPS_TO_PP1(a) pic_param->a = pps->a; +#define PPS_TO_PP2(a, b) pic_param->a = pps->b; +#define PPS_TO_PP(...) ARG_SEL(__VA_ARGS__, PPS_TO_PP2, PPS_TO_PP1)(__VA_ARGS__) +void D3D11H265Accelerator::PicParamsFromPPS(DXVA_PicParams_HEVC* pic_param, + const H265PPS* pps) { + PPS_TO_PP(num_ref_idx_l0_default_active_minus1); + PPS_TO_PP(num_ref_idx_l1_default_active_minus1); + PPS_TO_PP(init_qp_minus26); + + // dwCodingParamToolFlags from PPS + PPS_TO_PP(dependent_slice_segments_enabled_flag); + PPS_TO_PP(output_flag_present_flag); + PPS_TO_PP(num_extra_slice_header_bits); + PPS_TO_PP(sign_data_hiding_enabled_flag); + PPS_TO_PP(cabac_init_present_flag); + + // dwCodingSettingPicturePropertyFlags from PPS + PPS_TO_PP(constrained_intra_pred_flag); + PPS_TO_PP(transform_skip_enabled_flag); + PPS_TO_PP(cu_qp_delta_enabled_flag); + PPS_TO_PP(pps_slice_chroma_qp_offsets_present_flag); + PPS_TO_PP(weighted_pred_flag); + PPS_TO_PP(weighted_bipred_flag); + PPS_TO_PP(transquant_bypass_enabled_flag); + PPS_TO_PP(tiles_enabled_flag); + PPS_TO_PP(entropy_coding_sync_enabled_flag); + PPS_TO_PP(uniform_spacing_flag); + PPS_TO_PP(loop_filter_across_tiles_enabled_flag); + PPS_TO_PP(pps_loop_filter_across_slices_enabled_flag); + PPS_TO_PP(deblocking_filter_override_enabled_flag); + PPS_TO_PP(pps_deblocking_filter_disabled_flag); + PPS_TO_PP(lists_modification_present_flag); + PPS_TO_PP(slice_segment_header_extension_present_flag); + + PPS_TO_PP(pps_cb_qp_offset); + PPS_TO_PP(pps_cr_qp_offset); + if (pps->tiles_enabled_flag) { + PPS_TO_PP(num_tile_columns_minus1); + PPS_TO_PP(num_tile_rows_minus1); + if (!pps->uniform_spacing_flag) { + for (int i = 0; i <= pps->num_tile_columns_minus1; i++) { + PPS_TO_PP(column_width_minus1[i]); + } + for (int j = 0; j <= pps->num_tile_rows_minus1; j++) { + PPS_TO_PP(row_height_minus1[j]); + } + } + } + PPS_TO_PP(diff_cu_qp_delta_depth); + PPS_TO_PP(pps_beta_offset_div2); + PPS_TO_PP(pps_tc_offset_div2); + PPS_TO_PP(log2_parallel_merge_level_minus2); + + return; +} +#undef PPS_TO_PP +#undef PPS_TO_PP2 +#undef PPS_TO_PP1 +#undef ARG_SEL + +void D3D11H265Accelerator::PicParamsFromSliceHeader( + DXVA_PicParams_HEVC* pic_param, + const H265SPS* sps, + const H265SliceHeader* slice_hdr) { + // IDR_W_RADL and IDR_N_LP NALUs do not contain st_rps in slice header. + // Otherwise if short_term_ref_pic_set_sps_flag is 1, host decoder + // shall set ucNumDeltaPocsOfRefRpsIdx to 0. + if (slice_hdr->short_term_ref_pic_set_sps_flag || !slice_hdr->st_rps_bits) { + pic_param->ucNumDeltaPocsOfRefRpsIdx = 0; + pic_param->wNumBitsForShortTermRPSInSlice = 0; + } else { + pic_param->ucNumDeltaPocsOfRefRpsIdx = + slice_hdr->GetStRefPicSet(sps).num_delta_pocs; + pic_param->wNumBitsForShortTermRPSInSlice = slice_hdr->st_rps_bits; + } + pic_param->IrapPicFlag = slice_hdr->irap_pic; + auto nal_unit_type = slice_hdr->nal_unit_type; + pic_param->IdrPicFlag = (nal_unit_type == H265NALU::IDR_W_RADL || + nal_unit_type == H265NALU::IDR_N_LP); + pic_param->IntraPicFlag = slice_hdr->irap_pic; +} + +void D3D11H265Accelerator::PicParamsFromPic(DXVA_PicParams_HEVC* pic_param, + D3D11H265Picture* pic) { + pic_param->CurrPicOrderCntVal = pic->pic_order_cnt_val_; + pic_param->CurrPic.Index7Bits = pic->picture_index_; +} + +bool D3D11H265Accelerator::PicParamsFromRefLists( + DXVA_PicParams_HEVC* pic_param, + const H265Picture::Vector& ref_pic_list0, + const H265Picture::Vector& ref_pic_list1) { + if (ref_pic_list0.size() > kMaxRefPicListSize || + ref_pic_list1.size() > kMaxRefPicListSize) { + DLOG(ERROR) << "Invalid ref lists size."; + return false; + } + + constexpr int kDxvaInvalidRefPicIndex = 0xFF; + constexpr unsigned kStLtRpsSize = 8; + + std::fill_n(pic_param->RefPicSetStCurrBefore, kStLtRpsSize, + kDxvaInvalidRefPicIndex); + std::fill_n(pic_param->RefPicSetStCurrAfter, kStLtRpsSize, + kDxvaInvalidRefPicIndex); + std::fill_n(pic_param->RefPicSetLtCurr, kStLtRpsSize, + kDxvaInvalidRefPicIndex); + std::copy(ref_frame_pocs_, ref_frame_pocs_ + kMaxRefPicListSize - 1, + pic_param->PicOrderCntValList); + + // They store the indices into pic_param->RefPicList, not poc. + std::vector<int> pocs_st_curr_before, pocs_st_curr_after, pocs_lt_curr; + // Picture in list0 and list1 may overlap and should + // not be added duplicated. +#define ADD_IF_ABSENT(vec, elem) \ + do { \ + if (std::find(vec.begin(), vec.end(), elem) == vec.end()) \ + vec.push_back(elem); \ + } while (0) + + for (auto& it : ref_pic_list0) { + auto poc = it->pic_order_cnt_val_; + auto idx = poc_index_into_ref_pic_list_[poc]; + if (idx < 0) { + DLOG(ERROR) << "Invalid index of POC for ref list0."; + return false; + } + switch (it->ref_) { + case H265Picture::kShortTermCurrBefore: + ADD_IF_ABSENT(pocs_st_curr_before, idx); + break; + case H265Picture::kShortTermCurrAfter: + ADD_IF_ABSENT(pocs_st_curr_after, idx); + break; + case H265Picture::kLongTermCurr: + ADD_IF_ABSENT(pocs_lt_curr, idx); + break; + case H265Picture::kUnused: + case H265Picture::kShortTermFoll: + case H265Picture::kLongTermFoll: + break; + } + } + for (auto& it : ref_pic_list1) { + auto poc = it->pic_order_cnt_val_; + auto idx = poc_index_into_ref_pic_list_[poc]; + if (idx < 0) { + DLOG(ERROR) << "Invalid index of POC for ref list1."; + return false; + } + switch (it->ref_) { + case H265Picture::kShortTermCurrBefore: + ADD_IF_ABSENT(pocs_st_curr_before, idx); + break; + case H265Picture::kShortTermCurrAfter: + ADD_IF_ABSENT(pocs_st_curr_after, idx); + break; + case H265Picture::kLongTermCurr: + ADD_IF_ABSENT(pocs_lt_curr, idx); + break; + case H265Picture::kUnused: + case H265Picture::kShortTermFoll: + case H265Picture::kLongTermFoll: + break; + } + } +#undef ADD_IF_ABSENT + + if (pocs_st_curr_before.size() > kStLtRpsSize || + pocs_st_curr_after.size() > kStLtRpsSize || + pocs_lt_curr.size() > kStLtRpsSize) { + DLOG(ERROR) << "Invalid current short/long term ref pic set."; + return false; + } + + int idx = 0; + for (auto poc : pocs_st_curr_before) { + pic_param->RefPicSetStCurrBefore[idx++] = poc; + } + idx = 0; + for (auto poc : pocs_st_curr_after) { + pic_param->RefPicSetStCurrAfter[idx++] = poc; + } + idx = 0; + for (auto poc : pocs_lt_curr) { + pic_param->RefPicSetLtCurr[idx++] = poc; + } + return true; +} + +DecoderStatus D3D11H265Accelerator::SubmitSlice( + const H265SPS* sps, + const H265PPS* pps, + const H265SliceHeader* slice_hdr, + const H265Picture::Vector& ref_pic_list0, + const H265Picture::Vector& ref_pic_list1, + scoped_refptr<H265Picture> pic, + const uint8_t* data, + size_t size, + const std::vector<SubsampleEntry>& subsamples) { + DXVA_PicParams_HEVC pic_param = {}; + + D3D11H265Picture* d3d11_pic = pic->AsD3D11H265Picture(); + if (!d3d11_pic) { + return DecoderStatus::kFail; + } + + FillPicParamsWithConstants(&pic_param); + PicParamsFromSPS(&pic_param, sps); + PicParamsFromPPS(&pic_param, pps); + PicParamsFromSliceHeader(&pic_param, sps, slice_hdr); + PicParamsFromPic(&pic_param, d3d11_pic); + memcpy(pic_param.RefPicList, ref_frame_list_, sizeof pic_param.RefPicList); + + if (!PicParamsFromRefLists(&pic_param, ref_pic_list0, ref_pic_list1)) { + return DecoderStatus::kFail; + } + + pic_param.StatusReportFeedbackNumber = current_status_report_feedback_num_++; + + UINT buffer_size; + void* buffer; + HRESULT hr = video_context_->GetDecoderBuffer( + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS, + &buffer_size, &buffer); + if (!SUCCEEDED(hr)) { + RecordFailure("GetDecoderBuffer (PictureParams) failed", + D3D11Status::Codes::kGetPicParamBufferFailed, hr); + return DecoderStatus::kFail; + } + + memcpy(buffer, &pic_param, sizeof(pic_param)); + hr = video_context_->ReleaseDecoderBuffer( + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS); + if (!SUCCEEDED(hr)) { + RecordFailure("ReleaseDecoderBuffer (PictureParams) failed", + D3D11Status::Codes::kReleasePicParamBufferFailed, hr); + return DecoderStatus::kFail; + } + + // Fill up the quantitization matrix data structure when + // pps->scaling_list_enabled is true. See section 4.2 + // of DXVA spec for HEVC. + if (use_scaling_lists_) { + DXVA_Qmatrix_HEVC iq_matrix_buf = {}; + const H265ScalingListData* scaling_lists = + pps->pps_scaling_list_data_present_flag ? &pps->scaling_list_data + : &sps->scaling_list_data; + + for (int i = 0; i < 6; ++i) { + iq_matrix_buf.ucScalingListDCCoefSizeID2[i] = + scaling_lists->scaling_list_dc_coef_16x16[i]; + for (int j = 0; j < 16; ++j) { + iq_matrix_buf.ucScalingLists0[i][j] = + scaling_lists->scaling_list_4x4[i][j]; + } + + for (int j = 0; j < 64; ++j) { + iq_matrix_buf.ucScalingLists1[i][j] = + scaling_lists->scaling_list_8x8[i][j]; + iq_matrix_buf.ucScalingLists2[i][j] = + scaling_lists->scaling_list_16x16[i][j]; + } + } + for (int i = 0; i < 6; i += 3) { + iq_matrix_buf.ucScalingListDCCoefSizeID3[i / 3] = + scaling_lists->scaling_list_dc_coef_32x32[i]; + for (int j = 0; j < 64; ++j) { + iq_matrix_buf.ucScalingLists3[i / 3][j] = + scaling_lists->scaling_list_32x32[i][j]; + } + } + + hr = video_context_->GetDecoderBuffer( + video_decoder_.Get(), + D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX, &buffer_size, + &buffer); + if (!SUCCEEDED(hr)) { + RecordFailure("GetDecoderBuffer (QuantMatrix) failed", + D3D11Status::Codes::kGetQuantBufferFailed, hr); + return DecoderStatus::kFail; + } + memcpy(buffer, &iq_matrix_buf, sizeof(iq_matrix_buf)); + hr = video_context_->ReleaseDecoderBuffer( + video_decoder_.Get(), + D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX); + if (!SUCCEEDED(hr)) { + RecordFailure("ReleaseDecoderBuffer (QuantMatrix) failed", + D3D11Status::Codes::kReleaseQuantBufferFailed, hr); + return DecoderStatus::kFail; + } + } + + // Ideally all slices in a frame are put in the same bitstream buffer. + // However the bitstream buffer may not fit all the data, so split on the + // necessary boundaries. + size_t out_bitstream_size = size + 3; + size_t remaining_bitstream = out_bitstream_size; + size_t start_location = 0; + + if (pic->decrypt_config()) { + // For now, the entire frame has to fit into the bitstream buffer. This way + // the subsample ClearSize adjustment below should work. + if (bitstream_buffer_size_ < remaining_bitstream) { + RecordFailure("Input slice NALU (" + + base::NumberToString(remaining_bitstream) + + ") too big to fit in the bistream buffer (" + + base::NumberToString(bitstream_buffer_size_) + ").", + D3D11Status::Codes::kBitstreamBufferSliceTooBig); + return DecoderStatus::kFail; + } + + AppendSubsamples(subsamples, &subsamples_); + if (!subsamples.empty()) { + // Follow same logic as D3D11H264Accelerator. + subsamples_[subsamples_.size() - subsamples.size()].ClearSize += 3; + } + } + + while (remaining_bitstream > 0) { + if (bitstream_buffer_size_ < remaining_bitstream && + slice_info_.size() > 0) { + if (!SubmitSliceData()) + return DecoderStatus::kFail; + + if (!RetrieveBitstreamBuffer()) + return DecoderStatus::kFail; + } + + size_t bytes_to_copy = remaining_bitstream; + bool contains_end = true; + if (bytes_to_copy > bitstream_buffer_size_) { + bytes_to_copy = bitstream_buffer_size_; + contains_end = false; + } + size_t real_bytes_to_copy = bytes_to_copy; + uint8_t* out_start = bitstream_buffer_bytes_; + if (bytes_to_copy >= 3 && start_location == 0) { + *(out_start++) = 0; + *(out_start++) = 0; + *(out_start++) = 1; + real_bytes_to_copy -= 3; + } + memcpy(out_start, data + start_location, real_bytes_to_copy); + + DXVA_Slice_HEVC_Short slice_info = {}; + slice_info.BSNALunitDataLocation = (UINT)current_offset_; + slice_info.SliceBytesInBuffer = (UINT)bytes_to_copy; + if (contains_end && start_location == 0) + slice_info.wBadSliceChopping = 0; + else if (!contains_end && start_location == 0) + slice_info.wBadSliceChopping = 1; + else if (contains_end && start_location != 0) + slice_info.wBadSliceChopping = 2; + else + slice_info.wBadSliceChopping = 3; + + slice_info_.push_back(slice_info); + bitstream_buffer_size_ -= bytes_to_copy; + current_offset_ += bytes_to_copy; + start_location += bytes_to_copy; + remaining_bitstream -= bytes_to_copy; + bitstream_buffer_bytes_ += bytes_to_copy; + } + + return DecoderStatus::kOk; +} + +bool D3D11H265Accelerator::SubmitSliceData() { + if (slice_info_.size() <= 0) { + DLOG(ERROR) << "Invalid slice info size."; + return false; + } + + UINT buffer_size; + void* buffer; + + HRESULT hr = video_context_->GetDecoderBuffer( + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL, + &buffer_size, &buffer); + if (!SUCCEEDED(hr)) { + RecordFailure("GetDecoderBuffer (SliceControl) failed", + D3D11Status::Codes::kGetSliceControlBufferFailed, hr); + return false; + } + + if (sizeof(slice_info_[0]) * slice_info_.size() > buffer_size) { + DLOG(ERROR) << "Slice info size larger than decoder buffer size."; + return false; + } + memcpy(buffer, &slice_info_[0], sizeof(slice_info_[0]) * slice_info_.size()); + hr = video_context_->ReleaseDecoderBuffer( + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL); + if (!SUCCEEDED(hr)) { + RecordFailure("ReleaseDecoderBuffer (SliceControl) failed", + D3D11Status::Codes::kReleaseSliceControlBufferFailed, hr); + return false; + } + + hr = video_context_->ReleaseDecoderBuffer( + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_BITSTREAM); + if (!SUCCEEDED(hr)) { + RecordFailure("ReleaseDecoderBuffer (BitStream) failed", + D3D11Status::Codes::kReleaseBitstreamBufferFailed, hr); + return false; + } + + VideoContextWrapper::VideoBufferWrapper buffers[4] = {}; + buffers[0].BufferType = D3D11_VIDEO_DECODER_BUFFER_PICTURE_PARAMETERS; + buffers[0].DataOffset = 0; + buffers[0].DataSize = sizeof(DXVA_PicParams_HEVC); + buffers[1].BufferType = D3D11_VIDEO_DECODER_BUFFER_SLICE_CONTROL; + buffers[1].DataOffset = 0; + buffers[1].DataSize = sizeof(slice_info_[0]) * slice_info_.size(); + buffers[2].BufferType = D3D11_VIDEO_DECODER_BUFFER_BITSTREAM; + buffers[2].DataOffset = 0; + buffers[2].DataSize = current_offset_; + if (use_scaling_lists_) { + buffers[3].BufferType = + D3D11_VIDEO_DECODER_BUFFER_INVERSE_QUANTIZATION_MATRIX; + buffers[3].DataOffset = 0; + buffers[3].DataSize = sizeof(DXVA_Qmatrix_HEVC); + } + + if (!frame_iv_.empty()) { + buffers[2].pIV = frame_iv_.data(); + buffers[2].IVSize = frame_iv_.size(); + // Subsmaples matter iff there is IV, for decryption. + if (!subsamples_.empty()) { + buffers[2].pSubSampleMappingBlock = subsamples_.data(); + buffers[2].SubSampleMappingCount = subsamples_.size(); + } + } + + hr = video_context_->SubmitDecoderBuffers( + video_decoder_.Get(), + use_scaling_lists_ ? base::size(buffers) : base::size(buffers) - 1, + buffers); + current_offset_ = 0; + slice_info_.clear(); + bitstream_buffer_bytes_ = nullptr; + bitstream_buffer_size_ = 0; + frame_iv_.clear(); + subsamples_.clear(); + if (!SUCCEEDED(hr)) { + RecordFailure("SubmitDecoderBuffers failed", + D3D11Status::Codes::kSubmitDecoderBuffersFailed, hr); + return false; + } + + return true; +} + +DecoderStatus D3D11H265Accelerator::SubmitDecode( + scoped_refptr<H265Picture> pic) { + if (!SubmitSliceData()) + return DecoderStatus::kFail; + + HRESULT hr = video_context_->DecoderEndFrame(video_decoder_.Get()); + if (!SUCCEEDED(hr)) { + RecordFailure("DecoderEndFrame failed", + D3D11Status::Codes::kDecoderEndFrameFailed, hr); + return DecoderStatus::kFail; + } + + return DecoderStatus::kOk; +} + +void D3D11H265Accelerator::Reset() { + if (!bitstream_buffer_bytes_) + return; + + HRESULT hr = video_context_->ReleaseDecoderBuffer( + video_decoder_.Get(), D3D11_VIDEO_DECODER_BUFFER_BITSTREAM); + + bitstream_buffer_bytes_ = nullptr; + bitstream_buffer_size_ = 0; + current_offset_ = 0; + CHECK(SUCCEEDED(hr)); +} + +bool D3D11H265Accelerator::OutputPicture(scoped_refptr<H265Picture> pic) { + D3D11H265Picture* our_pic = pic->AsD3D11H265Picture(); + return our_pic && client_->OutputResult(our_pic, our_pic->picture); +} + +void D3D11H265Accelerator::RecordFailure(const std::string& reason, + D3D11Status::Codes code, + HRESULT hr) const { + std::string hr_string; + if (!SUCCEEDED(hr)) + hr_string = ": " + logging::SystemErrorCodeToString(hr); + + DLOG(ERROR) << reason << hr_string; + MEDIA_LOG(ERROR, media_log_) << hr_string << ": " << reason; +} + +void D3D11H265Accelerator::RecordFailure(D3D11Status error) const { + RecordFailure(error.message(), error.code()); +} + +void D3D11H265Accelerator::SetVideoDecoder(ComD3D11VideoDecoder video_decoder) { + video_decoder_ = std::move(video_decoder); +} + +} // namespace media
diff --git a/media/gpu/windows/d3d11_h265_accelerator.h b/media/gpu/windows/d3d11_h265_accelerator.h new file mode 100644 index 0000000..e00605d4 --- /dev/null +++ b/media/gpu/windows/d3d11_h265_accelerator.h
@@ -0,0 +1,137 @@ +// Copyright 2022 The Chromium 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_GPU_WINDOWS_D3D11_H265_ACCELERATOR_H_ +#define MEDIA_GPU_WINDOWS_D3D11_H265_ACCELERATOR_H_ + +#include <d3d11_1.h> +#include <d3d9.h> +#include <dxva.h> +#include <wrl/client.h> + +#include <vector> + +#include "base/memory/raw_ptr.h" +#include "gpu/command_buffer/service/texture_manager.h" +#include "media/base/video_frame.h" +#include "media/base/win/mf_helpers.h" +#include "media/gpu/h265_decoder.h" +#include "media/gpu/h265_dpb.h" +#include "media/gpu/windows/d3d11_com_defs.h" +#include "media/gpu/windows/d3d11_status.h" +#include "media/gpu/windows/d3d11_video_context_wrapper.h" +#include "media/gpu/windows/d3d11_video_decoder_client.h" +#include "media/video/picture.h" +#include "third_party/angle/include/EGL/egl.h" +#include "third_party/angle/include/EGL/eglext.h" +#include "ui/gl/gl_image.h" + +namespace media { + +// Maximum of valid DXVA_PicEntry_HEVC entries in RefPicList +constexpr unsigned kMaxRefPicListSize = 15; + +class D3D11H265Accelerator; +class MediaLog; + +class D3D11H265Accelerator : public H265Decoder::H265Accelerator { + public: + D3D11H265Accelerator(D3D11VideoDecoderClient* client, + MediaLog* media_log, + ComD3D11VideoDevice video_device, + std::unique_ptr<VideoContextWrapper> video_context); + + D3D11H265Accelerator(const D3D11H265Accelerator&) = delete; + D3D11H265Accelerator& operator=(const D3D11H265Accelerator&) = delete; + + ~D3D11H265Accelerator() override; + + // H265Decoder::H265Accelerator implementation. + scoped_refptr<H265Picture> CreateH265Picture() override; + Status SubmitFrameMetadata(const H265SPS* sps, + const H265PPS* pps, + const H265SliceHeader* slice_hdr, + const H265Picture::Vector& ref_pic_list, + scoped_refptr<H265Picture> pic) override; + Status SubmitSlice(const H265SPS* sps, + const H265PPS* pps, + const H265SliceHeader* slice_hdr, + const H265Picture::Vector& ref_pic_list0, + const H265Picture::Vector& ref_pic_list1, + scoped_refptr<H265Picture> pic, + const uint8_t* data, + size_t size, + const std::vector<SubsampleEntry>& subsamples) override; + Status SubmitDecode(scoped_refptr<H265Picture> pic) override; + void Reset() override; + bool OutputPicture(scoped_refptr<H265Picture> pic) override; + + private: + bool SubmitSliceData(); + bool RetrieveBitstreamBuffer(); + + // Gets a pic params struct with the constant fields set. + void FillPicParamsWithConstants(DXVA_PicParams_HEVC* pic_param); + + // Populate the pic params with fields from the SPS structure. + void PicParamsFromSPS(DXVA_PicParams_HEVC* pic_param, const H265SPS* sps); + + // Populate the pic params with fields from the PPS structure. + void PicParamsFromPPS(DXVA_PicParams_HEVC* pic_param, const H265PPS* pps); + + // Populate the pic params with fields from the slice header structure. + void PicParamsFromSliceHeader(DXVA_PicParams_HEVC* pic_param, + const H265SPS* sps, + const H265SliceHeader* slice_hdr); + + // Populate the pic params with fields from the picture passed in. + void PicParamsFromPic(DXVA_PicParams_HEVC* pic_param, D3D11H265Picture* pic); + + // Populate the pic params with fields from ref_pic_list{0,1} + bool PicParamsFromRefLists(DXVA_PicParams_HEVC* pic_param, + const H265Picture::Vector& ref_pic_list0, + const H265Picture::Vector& ref_pic_list1); + + void SetVideoDecoder(ComD3D11VideoDecoder video_decoder); + + // Record a failure to DVLOG and |media_log_|. + void RecordFailure(const std::string& reason, + D3D11Status::Codes code, + HRESULT hr = S_OK) const; + void RecordFailure(D3D11Status error) const; + + raw_ptr<D3D11VideoDecoderClient> client_; + raw_ptr<MediaLog> media_log_ = nullptr; + + ComD3D11VideoDecoder video_decoder_; + ComD3D11VideoDevice video_device_; + std::unique_ptr<VideoContextWrapper> video_context_; + + // This information set at the beginning of a frame and saved for processing + // all the slices. + DXVA_PicEntry_HEVC ref_frame_list_[kMaxRefPicListSize]; + int ref_frame_pocs_[kMaxRefPicListSize]; + base::flat_map<int, int> poc_index_into_ref_pic_list_; + bool use_scaling_lists_ = false; + + // Information that's accumulated during slices and submitted at the end + std::vector<DXVA_Slice_HEVC_Short> slice_info_; + size_t current_offset_ = 0; + size_t bitstream_buffer_size_ = 0; + raw_ptr<uint8_t> bitstream_buffer_bytes_ = nullptr; + + // For HEVC this number needs to be larger than 1 and different + // in each call to Execute(). + int current_status_report_feedback_num_ = 1; + + // This contains the subsamples (clear and encrypted) of the slice data + // in D3D11_VIDEO_DECODER_BUFFER_BITSTREAM buffer. + std::vector<D3D11_VIDEO_DECODER_SUB_SAMPLE_MAPPING_BLOCK> subsamples_; + // IV for the current frame. + std::vector<uint8_t> frame_iv_; +}; + +} // namespace media + +#endif // MEDIA_GPU_WINDOWS_D3D11_H265_ACCELERATOR_H_
diff --git a/media/mojo/mojom/key_system_support.mojom b/media/mojo/mojom/key_system_support.mojom index 12e4527..de2967f 100644 --- a/media/mojo/mojom/key_system_support.mojom +++ b/media/mojo/mojom/key_system_support.mojom
@@ -37,8 +37,6 @@ // the list of registered CDMs, and hardware secure support check also needs // to run in the browser process because the render process is sandboxed. // KeySystemSupport clients run in the renderer process. - // TODO(crbug.com/853264): Make this an async call. - [Sync] IsKeySystemSupported(string key_system) => (bool is_supported, KeySystemCapability? key_system_capability); };
diff --git a/media/renderers/paint_canvas_video_renderer.cc b/media/renderers/paint_canvas_video_renderer.cc index 693a4559..fb833ab 100644 --- a/media/renderers/paint_canvas_video_renderer.cc +++ b/media/renderers/paint_canvas_video_renderer.cc
@@ -458,6 +458,12 @@ case PIXEL_FORMAT_YUV422P10: convert_yuv16(matrix, libyuv::I210ToARGBMatrix); break; + case PIXEL_FORMAT_YUV444P10: + convert_yuv16(matrix, libyuv::I410ToARGBMatrix); + break; + case PIXEL_FORMAT_YUV420P12: + convert_yuv16(matrix, libyuv::I012ToARGBMatrix); + break; case PIXEL_FORMAT_I420A: libyuv::I420AlphaToARGBMatrix( @@ -483,8 +489,6 @@ case PIXEL_FORMAT_YUV420P9: case PIXEL_FORMAT_YUV422P9: case PIXEL_FORMAT_YUV444P9: - case PIXEL_FORMAT_YUV444P10: - case PIXEL_FORMAT_YUV420P12: case PIXEL_FORMAT_YUV422P12: case PIXEL_FORMAT_YUV444P12: case PIXEL_FORMAT_Y16: @@ -1188,18 +1192,17 @@ case PIXEL_FORMAT_YUV420P9: case PIXEL_FORMAT_YUV422P9: case PIXEL_FORMAT_YUV444P9: - case PIXEL_FORMAT_YUV444P10: - case PIXEL_FORMAT_YUV420P12: case PIXEL_FORMAT_YUV422P12: case PIXEL_FORMAT_YUV444P12: temporary_frame = DownShiftHighbitVideoFrame(video_frame); video_frame = temporary_frame.get(); break; case PIXEL_FORMAT_YUV420P10: + case PIXEL_FORMAT_YUV420P12: // In AV1, a monochrome (grayscale) frame is represented as a YUV 4:2:0 - // frame with no U and V planes. Since there are no 10-bit versions of - // libyuv::I400ToARGB() and libyuv::J400ToARGB(), convert the frame to an - // 8-bit YUV 4:2:0 frame with U and V planes. + // frame with no U and V planes. Since there are no 10-bit and 12-bit + // versions of libyuv::I400ToARGBMatrix(), convert the frame to an 8-bit + // YUV 4:2:0 frame with U and V planes. if (!video_frame->data(VideoFrame::kUPlane) && !video_frame->data(VideoFrame::kVPlane)) { temporary_frame = DownShiftHighbitVideoFrame(video_frame);
diff --git a/net/BUILD.gn b/net/BUILD.gn index 3b00bcf3..8ceb09f4 100644 --- a/net/BUILD.gn +++ b/net/BUILD.gn
@@ -841,8 +841,6 @@ "quic/web_transport_client.h", "quic/web_transport_error.cc", "quic/web_transport_error.h", - "quiche/common/platform/impl/quiche_command_line_flags_impl.cc", - "quiche/common/platform/impl/quiche_command_line_flags_impl.h", "quiche/common/platform/impl/quiche_flag_utils_impl.h", "quiche/common/platform/impl/quiche_flags_impl.cc", "quiche/common/platform/impl/quiche_flags_impl.h", @@ -4576,7 +4574,6 @@ sources += [ "quic/platform/impl/quic_epoll_clock_test.cc", "quic/platform/impl/quic_flags_test.cc", - "quiche/common/platform/impl/quiche_command_line_flags_test.cc", "tools/quic/quic_http_proxy_backend_stream_test.cc", "tools/quic/quic_http_proxy_backend_test.cc", "tools/quic/quic_simple_server_test.cc",
diff --git a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java index b83869d0..e95552b3 100644 --- a/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java +++ b/net/android/java/src/org/chromium/net/NetworkChangeNotifierAutoDetect.java
@@ -200,7 +200,6 @@ * @param networkInfo The NetworkInfo for the active network. * @return the info of the network that is available to this app. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) private NetworkInfo processActiveNetworkInfo(NetworkInfo networkInfo) { if (networkInfo == null) { return null; @@ -281,7 +280,6 @@ * getNetworkInfo(Network) for a method that does. * Only callable on Lollipop and newer releases. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) NetworkInfo getRawNetworkInfo(Network network) { try { return mConnectivityManager.getNetworkInfo(network); @@ -299,7 +297,6 @@ * Fetches NetworkInfo for |network|. * Only callable on Lollipop and newer releases. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) NetworkInfo getNetworkInfo(Network network) { NetworkInfo networkInfo = getRawNetworkInfo(network); if (networkInfo != null && networkInfo.getType() == TYPE_VPN) { @@ -315,7 +312,6 @@ * Returns connection type for |network|. * Only callable on Lollipop and newer releases. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) @ConnectionType int getConnectionType(Network network) { NetworkInfo networkInfo = getNetworkInfo(network); @@ -331,7 +327,6 @@ * another user); use {@link getAllNetworks} for a filtered list. * Only callable on Lollipop and newer releases. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) @VisibleForTesting protected Network[] getAllNetworksUnfiltered() { Network[] networks = mConnectivityManager.getAllNetworks(); @@ -343,7 +338,6 @@ * Returns {@code true} if {@code network} applies to (and hence is accessible) to the * current user. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) @VisibleForTesting protected boolean vpnAccessible(Network network) { // Determine if the VPN applies to the current user by seeing if a socket can be bound @@ -372,7 +366,6 @@ * Return the NetworkCapabilities for {@code network}, or {@code null} if they cannot * be retrieved (e.g. {@code network} has disconnected). */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) @VisibleForTesting protected NetworkCapabilities getNetworkCapabilities(Network network) { final int retryCount = 2; @@ -393,7 +386,6 @@ * that satisfy networkRequest. * Only callable on Lollipop and newer releases. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) void registerNetworkCallback( NetworkRequest networkRequest, NetworkCallback networkCallback, Handler handler) { // Starting with Oreo specifying a Handler is allowed. Use this to avoid thread-hops. @@ -419,7 +411,6 @@ * Unregisters networkCallback from receiving notifications. * Only callable on Lollipop and newer releases. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) void unregisterNetworkCallback(NetworkCallback networkCallback) { mConnectivityManager.unregisterNetworkCallback(networkCallback); } @@ -428,7 +419,6 @@ * Returns the current default {@link Network}, or {@code null} if disconnected. * Only callable on Lollipop and newer releases. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) Network getDefaultNetwork() { Network defaultNetwork = null; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { @@ -550,7 +540,6 @@ } // NetworkCallback used for listening for changes to the default network. - @TargetApi(Build.VERSION_CODES.LOLLIPOP) private class DefaultNetworkCallback extends NetworkCallback { // If registered, notify connectionTypeChanged() to look for changes. @Override @@ -669,7 +658,6 @@ // and go. It gets called back on a special handler thread // ConnectivityManager creates for making the callbacks. The callbacks in // turn post to mLooper where mObserver lives. - @TargetApi(Build.VERSION_CODES.LOLLIPOP) private class MyNetworkCallback extends NetworkCallback { // If non-null, this indicates a VPN is in place for the current user, and no other // networks are accessible. @@ -951,7 +939,6 @@ * for network changes (e.g. see (@link RegistrationPolicyAlwaysRegister} and * {@link RegistrationPolicyApplicationStatus}). */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) public NetworkChangeNotifierAutoDetect(Observer observer, RegistrationPolicy policy) { mLooper = Looper.myLooper(); mHandler = new Handler(mLooper); @@ -1145,7 +1132,6 @@ * Only callable on Lollipop and newer releases. * @param ignoreNetwork ignore this network as if it is not connected. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) private static Network[] getAllNetworksFiltered( ConnectivityManagerDelegate connectivityManagerDelegate, Network ignoreNetwork) { Network[] networks = connectivityManagerDelegate.getAllNetworksUnfiltered(); @@ -1311,7 +1297,6 @@ * Extracts NetID of Network on Lollipop and NetworkHandle (which is munged NetID) on * Marshmallow and newer releases. Only available on Lollipop and newer releases. */ - @TargetApi(Build.VERSION_CODES.LOLLIPOP) public static long networkToNetId(Network network) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return ApiHelperForM.getNetworkHandle(network);
diff --git a/net/android/java/src/org/chromium/net/ProxyChangeListener.java b/net/android/java/src/org/chromium/net/ProxyChangeListener.java index 7ff942e0..a9f8f04 100644 --- a/net/android/java/src/org/chromium/net/ProxyChangeListener.java +++ b/net/android/java/src/org/chromium/net/ProxyChangeListener.java
@@ -73,7 +73,6 @@ mExclusionList = exclusionList; } - @TargetApi(Build.VERSION_CODES.LOLLIPOP) private static ProxyConfig fromProxyInfo(ProxyInfo proxyInfo) { if (proxyInfo == null) { return null;
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc index 36ea770..f50ed5c 100644 --- a/net/http/http_response_info.cc +++ b/net/http/http_response_info.cc
@@ -168,7 +168,6 @@ case CONNECTION_INFO_QUIC_DRAFT_29: case CONNECTION_INFO_QUIC_T051: case CONNECTION_INFO_QUIC_RFC_V1: - case CONNECTION_INFO_QUIC_2_DRAFT_1: return CONNECTION_INFO_COARSE_QUIC; case CONNECTION_INFO_UNKNOWN: @@ -528,7 +527,6 @@ case CONNECTION_INFO_QUIC_DRAFT_29: case CONNECTION_INFO_QUIC_T051: case CONNECTION_INFO_QUIC_RFC_V1: - case CONNECTION_INFO_QUIC_2_DRAFT_1: return true; case NUM_OF_CONNECTION_INFOS: NOTREACHED(); @@ -627,8 +625,6 @@ return "h3-T051"; case CONNECTION_INFO_QUIC_RFC_V1: return "h3"; - case CONNECTION_INFO_QUIC_2_DRAFT_1: - return "quic2/1"; case NUM_OF_CONNECTION_INFOS: break; }
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h index a6d80e49..86d157aa 100644 --- a/net/http/http_response_info.h +++ b/net/http/http_response_info.h
@@ -77,7 +77,6 @@ CONNECTION_INFO_QUIC_DRAFT_29 = 38, CONNECTION_INFO_QUIC_T051 = 39, CONNECTION_INFO_QUIC_RFC_V1 = 40, - CONNECTION_INFO_QUIC_2_DRAFT_1 = 41, NUM_OF_CONNECTION_INFOS, };
diff --git a/net/http/http_server_properties_manager_unittest.cc b/net/http/http_server_properties_manager_unittest.cc index e8f7973..dffc4d00 100644 --- a/net/http/http_server_properties_manager_unittest.cc +++ b/net/http/http_server_properties_manager_unittest.cc
@@ -3036,13 +3036,12 @@ AlternativeServiceInfoVector alternative_service_info_vector_out = server_info.alternative_services.value(); ASSERT_EQ(1u, alternative_service_info_vector_out.size()); - const auto& altsvc_info = alternative_service_info_vector_out[0]; - EXPECT_EQ(kProtoQUIC, altsvc_info.alternative_service().protocol); + EXPECT_EQ( + kProtoQUIC, + alternative_service_info_vector_out[0].alternative_service().protocol); // Ensure we correctly parsed the version. - // (Versions with identical ALPN string are considered equal.) - ASSERT_EQ(1u, altsvc_info.advertised_versions().size()); - EXPECT_EQ(quic::AlpnForVersion(version), - quic::AlpnForVersion(altsvc_info.advertised_versions()[0])); + EXPECT_EQ(advertised_versions, + alternative_service_info_vector_out[0].advertised_versions()); } }
diff --git a/net/quic/platform/impl/quic_default_proof_providers_impl.cc b/net/quic/platform/impl/quic_default_proof_providers_impl.cc index 341ab94..6d349ff 100644 --- a/net/quic/platform/impl/quic_default_proof_providers_impl.cc +++ b/net/quic/platform/impl/quic_default_proof_providers_impl.cc
@@ -17,25 +17,24 @@ #include "net/quic/crypto/proof_source_chromium.h" #include "net/quic/crypto/proof_verifier_chromium.h" #include "net/quic/platform/impl/quic_chromium_clock.h" -#include "net/third_party/quiche/src/common/platform/api/quiche_command_line_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/tools/simple_ticket_crypter.h" -DEFINE_QUICHE_COMMAND_LINE_FLAG( +DEFINE_QUIC_COMMAND_LINE_FLAG( bool, allow_unknown_root_cert, false, "If true, don't restrict cert verification to known roots"); -DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, - certificate_file, - "", - "Path to the certificate chain."); +DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, + certificate_file, + "", + "Path to the certificate chain."); -DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, - key_file, - "", - "Path to the pkcs8 private key."); +DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, + key_file, + "", + "Path to the pkcs8 private key."); using net::CertVerifier; using net::ProofVerifierChromium;
diff --git a/net/quic/platform/impl/quic_flags_impl.cc b/net/quic/platform/impl/quic_flags_impl.cc index 5eae6f4..5461b16 100644 --- a/net/quic/platform/impl/quic_flags_impl.cc +++ b/net/quic/platform/impl/quic_flags_impl.cc
@@ -4,9 +4,23 @@ #include "net/quic/platform/impl/quic_flags_impl.h" +#include <algorithm> +#include <initializer_list> +#include <iostream> +#include <limits> +#include <set> #include <string> +#include "base/command_line.h" +#include "base/export_template.h" +#include "base/logging.h" +#include "base/no_destructor.h" +#include "base/strings/strcat.h" #include "base/strings/string_number_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/utf_string_conversions.h" +#include "build/build_config.h" +#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" #define DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE(type, flag, value, doc) \ type FLAGS_##flag = value; @@ -32,6 +46,240 @@ #undef DEFINE_QUIC_PROTOCOL_FLAG_TWO_VALUES #undef DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE +namespace quic { + +namespace { + +// Overload for platforms where base::CommandLine::StringType == std::string. +[[maybe_unused]] std::vector<std::string> ToQuicStringVector( + const std::vector<std::string>& v) { + return v; +} + +#if defined(WCHAR_T_IS_UTF16) +// Overload for platforms where base::CommandLine::StringType == std::wstring. +[[maybe_unused]] std::vector<std::string> ToQuicStringVector( + const std::vector<std::wstring>& v) { + std::vector<std::string> qsv; + for (const auto& s : v) { + if (!base::IsStringASCII(s)) { + QUIC_LOG(ERROR) << "Unable to convert to ASCII: " << s; + continue; + } + qsv.push_back(base::WideToASCII(s)); + } + return qsv; +} +#endif // defined(WCHAR_T_IS_UTF16) + +size_t FindLineWrapPosition(const std::string& s, size_t desired_len) { + if (s.length() <= desired_len) { + return std::string::npos; + } + size_t pos = s.find_last_of(base::kWhitespaceASCII, desired_len); + if (pos != std::string::npos) { + return pos; + } + pos = s.find_first_of(base::kWhitespaceASCII, desired_len); + if (pos != std::string::npos) { + return pos; + } + return std::string::npos; +} + +// Pretty-print a flag description in the format: +// +// --flag_name Some text describing the flag that can +// wrap around to the next line. +void AppendFlagDescription(const std::string& name, + std::string help, + std::string* out) { + const int kStartCol = 20; + const int kEndCol = 80; + const int kMinPadding = 2; + static const char kDashes[] = "--"; + + base::StrAppend(out, {kDashes, name}); + int col = strlen(kDashes) + name.length(); + if (col + kMinPadding < kEndCol) { + // Start help text on same line + int pad_len = std::max(kMinPadding, kStartCol - col); + base::StrAppend(out, {std::string(pad_len, ' ')}); + col += pad_len; + } else { + // Start help text on next line + base::StrAppend(out, {"\n", std::string(kStartCol, ' ')}); + col = kStartCol; + } + + while (!help.empty()) { + size_t desired_len = kEndCol - col; + size_t wrap_pos = FindLineWrapPosition(help, desired_len); + if (wrap_pos == std::string::npos) { + base::StrAppend(out, {help}); + break; + } + base::StrAppend( + out, {help.substr(0, wrap_pos), "\n", std::string(kStartCol, ' ')}); + help = help.substr(wrap_pos + 1); + col = kStartCol; + } + base::StrAppend(out, {"\n"}); +} + +} // namespace + +// static +QuicFlagRegistry& QuicFlagRegistry::GetInstance() { + static base::NoDestructor<QuicFlagRegistry> instance; + return *instance; +} + +void QuicFlagRegistry::RegisterFlag(const char* name, + std::unique_ptr<QuicFlagHelper> helper) { + flags_.emplace(std::string(name), std::move(helper)); +} + +bool QuicFlagRegistry::SetFlags(const base::CommandLine& command_line, + std::string* error_msg) const { + for (const auto& kv : flags_) { + const std::string& name = kv.first; + const QuicFlagHelper* helper = kv.second.get(); + if (!command_line.HasSwitch(name)) { + continue; + } + std::string value = command_line.GetSwitchValueASCII(name); + if (!helper->SetFlag(value)) { + *error_msg = + base::StrCat({"Invalid value \"", value, "\" for flag --", name}); + return false; + } + QUIC_LOG(INFO) << "Set flag --" << name << " = " << value; + } + return true; +} + +void QuicFlagRegistry::ResetFlags() const { + for (const auto& kv : flags_) { + kv.second->ResetFlag(); + QUIC_LOG(INFO) << "Reset flag --" << kv.first; + } +} + +std::string QuicFlagRegistry::GetHelp() const { + std::string help; + AppendFlagDescription("help", "Print this help message.", &help); + for (const auto& kv : flags_) { + AppendFlagDescription(kv.first, kv.second->GetHelp(), &help); + } + return help; +} + +template <> +bool TypedQuicFlagHelper<bool>::SetFlag(const std::string& s) const { + static const base::NoDestructor<std::set<std::string>> kTrueValues( + std::initializer_list<std::string>({"", "1", "t", "true", "y", "yes"})); + static const base::NoDestructor<std::set<std::string>> kFalseValues( + std::initializer_list<std::string>({"0", "f", "false", "n", "no"})); + if (kTrueValues->find(base::ToLowerASCII(s)) != kTrueValues->end()) { + *flag_ = true; + return true; + } + if (kFalseValues->find(base::ToLowerASCII(s)) != kFalseValues->end()) { + *flag_ = false; + return true; + } + return false; +} + +template <> +bool TypedQuicFlagHelper<uint16_t>::SetFlag(const std::string& s) const { + int value; + if (!base::StringToInt(s, &value) || + value < std::numeric_limits<uint16_t>::min() || + value > std::numeric_limits<uint16_t>::max()) { + return false; + } + *flag_ = static_cast<uint16_t>(value); + return true; +} + +template <> +bool TypedQuicFlagHelper<int32_t>::SetFlag(const std::string& s) const { + int32_t value; + if (!base::StringToInt(s, &value)) { + return false; + } + *flag_ = value; + return true; +} + +template <> +bool TypedQuicFlagHelper<std::string>::SetFlag(const std::string& s) const { + *flag_ = s; + return true; +} + +template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE) + TypedQuicFlagHelper<bool>; +template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE) + TypedQuicFlagHelper<uint16_t>; +template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE) + TypedQuicFlagHelper<int32_t>; +template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE) + TypedQuicFlagHelper<std::string>; + +std::vector<std::string> QuicParseCommandLineFlagsImpl( + const char* usage, + int argc, + const char* const* argv) { + base::CommandLine::Init(argc, argv); + auto result = QuicParseCommandLineFlagsHelper( + usage, *base::CommandLine::ForCurrentProcess()); + if (result.exit_status.has_value()) { + exit(*result.exit_status); + } + + logging::LoggingSettings settings; + settings.logging_dest = logging::LOG_TO_STDERR; + CHECK(logging::InitLogging(settings)); + + return result.non_flag_args; +} + +QuicParseCommandLineFlagsResult QuicParseCommandLineFlagsHelper( + const char* usage, + const base::CommandLine& command_line) { + QuicParseCommandLineFlagsResult result; + result.non_flag_args = ToQuicStringVector(command_line.GetArgs()); + if (command_line.HasSwitch("h") || command_line.HasSwitch("help")) { + QuicPrintCommandLineFlagHelpImpl(usage); + result.exit_status = 0; + } else { + std::string msg; + if (!QuicFlagRegistry::GetInstance().SetFlags(command_line, &msg)) { + std::cerr << msg << std::endl; + result.exit_status = 1; + } + } + return result; +} + +void QuicPrintCommandLineFlagHelpImpl(const char* usage) { + std::cout << usage << std::endl + << "Options:" << std::endl + << QuicFlagRegistry::GetInstance().GetHelp() << std::endl; +} + +QuicFlagRegistry::QuicFlagRegistry() = default; +QuicFlagRegistry::~QuicFlagRegistry() = default; +QuicParseCommandLineFlagsResult::QuicParseCommandLineFlagsResult() = default; +QuicParseCommandLineFlagsResult::QuicParseCommandLineFlagsResult( + const QuicParseCommandLineFlagsResult&) = default; +QuicParseCommandLineFlagsResult::~QuicParseCommandLineFlagsResult() = default; + +} // namespace quic + namespace { void SetQuicFlagByName_bool(bool* flag, const std::string& value) {
diff --git a/net/quic/platform/impl/quic_flags_impl.h b/net/quic/platform/impl/quic_flags_impl.h index 99d11ca..3f679b6 100644 --- a/net/quic/platform/impl/quic_flags_impl.h +++ b/net/quic/platform/impl/quic_flags_impl.h
@@ -5,8 +5,16 @@ #ifndef NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_ #define NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_ +#include <cstdint> +#include <map> +#include <memory> #include <string> +#include <vector> +#include "base/command_line.h" +#include "base/export_template.h" +#include "base/memory/raw_ptr.h" +#include "base/no_destructor.h" #include "net/third_party/quiche/src/common/platform/api/quiche_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" #include "third_party/abseil-cpp/absl/types/optional.h" @@ -22,4 +30,141 @@ QUIC_EXPORT_PRIVATE void SetQuicFlagByName(const std::string& flag_name, const std::string& value); +namespace quic { + +// ------------------------------------------------------------------------ +// DEFINE_QUIC_COMMAND_LINE_FLAG implementation. +// ------------------------------------------------------------------------ + +// Abstract class for setting flags and fetching help strings. +class QuicFlagHelper { + public: + explicit QuicFlagHelper(const char* help) : help_(help) {} + virtual ~QuicFlagHelper() = default; + + virtual bool SetFlag(const std::string& value) const = 0; + virtual void ResetFlag() const = 0; + std::string GetHelp() const { return help_; } + + private: + std::string help_; +}; + +// Templated class for setting flags of various types. +template <typename T> +class TypedQuicFlagHelper : public QuicFlagHelper { + public: + TypedQuicFlagHelper(T* flag, const T& default_value, const char* help) + : QuicFlagHelper(help), flag_(flag), default_value_(default_value) {} + bool SetFlag(const std::string& value) const override; + void ResetFlag() const override { *flag_ = default_value_; } + + private: + mutable raw_ptr<T> flag_; + T default_value_; +}; + +// SetFlag specializations. Implementations in .cc file. +template <> +QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<bool>::SetFlag( + const std::string&) const; +template <> +QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<uint16_t>::SetFlag( + const std::string&) const; +template <> +QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<int32_t>::SetFlag( + const std::string&) const; +template <> +QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<std::string>::SetFlag( + const std::string&) const; + +// TypedQuicFlagHelper instantiations are in .cc file. +extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE) + TypedQuicFlagHelper<bool>; +extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE) + TypedQuicFlagHelper<uint16_t>; +extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE) + TypedQuicFlagHelper<int32_t>; +extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE) + TypedQuicFlagHelper<std::string>; + +// Registry of QuicFlagHelpers. +class QUIC_EXPORT_PRIVATE QuicFlagRegistry { + public: + ~QuicFlagRegistry(); + + static QuicFlagRegistry& GetInstance(); + + // Adds a flag to the registry. + void RegisterFlag(const char* name, std::unique_ptr<QuicFlagHelper> helper); + + // Sets any flags in the registry that are specified in |command_line|, + // returning true iff successful. If there is a failure, e.g. due to an + // invalid flag value, returns false and sets |error_msg|. + bool SetFlags(const base::CommandLine& command_line, + std::string* error_msg) const; + + // Resets flags to their default values. + void ResetFlags() const; + + // Returns a help string consisting of the names and help strings of all + // registered flags. + std::string GetHelp() const; + + private: + friend class base::NoDestructor<QuicFlagRegistry>; + + // Should only be accessed as a singleton. + QuicFlagRegistry(); + + std::map<std::string, std::unique_ptr<QuicFlagHelper>> flags_; +}; + +// Class instantiated in DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL macro expansion, +// that registers flag as a side effect of its constructor. Similar in spirit to +// absl::flags_internal::FlagRegistrar. +template <typename T> +class QuicFlagSetup { + public: + QuicFlagSetup(T* flag, + const char* name, + const T& default_value, + const char* help) { + QuicFlagRegistry::GetInstance().RegisterFlag( + name, + std::make_unique<TypedQuicFlagHelper<T>>(flag, default_value, help)); + } + // Allow QuicFlagSetup instance to convert to a bool in + // DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL macro expansion, so it can go away. + operator bool() const { return true; } +}; + +#define DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL(type, name, default_value, help) \ + type FLAGS_##name = default_value; \ + bool FLAGS_no##name = \ + quic::QuicFlagSetup<type>(&FLAGS_##name, #name, default_value, help) + +QUIC_EXPORT_PRIVATE std::vector<std::string> QuicParseCommandLineFlagsImpl( + const char* usage, + int argc, + const char* const* argv); + +// Used internally by QuicParseCommandLineFlagsImpl(), but exposed here for +// testing. +struct QUIC_EXPORT_PRIVATE QuicParseCommandLineFlagsResult { + QuicParseCommandLineFlagsResult(); + QuicParseCommandLineFlagsResult(const QuicParseCommandLineFlagsResult&); + ~QuicParseCommandLineFlagsResult(); + + std::vector<std::string> non_flag_args; + absl::optional<int> exit_status; +}; + +QUIC_EXPORT_PRIVATE QuicParseCommandLineFlagsResult +QuicParseCommandLineFlagsHelper(const char* usage, + const base::CommandLine& command_line); + +QUIC_EXPORT_PRIVATE void QuicPrintCommandLineFlagHelpImpl(const char* usage); + +} // namespace quic #endif // NET_QUIC_PLATFORM_IMPL_QUIC_FLAGS_IMPL_H_
diff --git a/net/quic/platform/impl/quic_flags_test.cc b/net/quic/platform/impl/quic_flags_test.cc index c36d946..d781872 100644 --- a/net/quic/platform/impl/quic_flags_test.cc +++ b/net/quic/platform/impl/quic_flags_test.cc
@@ -6,14 +6,184 @@ #include <string> +#include "base/command_line.h" #include "base/cxx17_backports.h" +#include "base/strings/strcat.h" +#include "base/strings/stringprintf.h" +#include "base/strings/utf_string_conversions.h" #include "net/quic/platform/impl/quic_flags_impl.h" #include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" #include "net/third_party/quiche/src/quic/platform/api/quic_test.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +DEFINE_QUIC_COMMAND_LINE_FLAG(bool, foo, false, "An old silent pond..."); +DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, bar, 123, "A frog jumps into the pond,"); +DEFINE_QUIC_COMMAND_LINE_FLAG(std::string, baz, "splash!", "Silence again."); namespace quic { namespace test { +class QuicCommandLineFlagTest : public QuicTest { + protected: + void SetUp() override { QuicFlagRegistry::GetInstance().ResetFlags(); } + + static QuicParseCommandLineFlagsResult QuicParseCommandLineFlagsForTest( + const char* usage, + int argc, + const char* const* argv) { + base::CommandLine::StringVector v; + FillCommandLineArgs(argc, argv, &v); + return QuicParseCommandLineFlagsHelper(usage, base::CommandLine(v)); + } + + private: + // Overload for platforms where base::CommandLine::StringType == std::string. + static void FillCommandLineArgs(int argc, + const char* const* argv, + std::vector<std::string>* v) { + for (int i = 0; i < argc; ++i) { + v->push_back(argv[i]); + } + } + + // Overload for platforms where base::CommandLine::StringType == + // std::u16string. + static void FillCommandLineArgs(int argc, + const char* const* argv, + std::vector<std::u16string>* v) { + for (int i = 0; i < argc; ++i) { + v->push_back(base::UTF8ToUTF16(argv[i])); + } + } +}; + +TEST_F(QuicCommandLineFlagTest, DefaultValues) { + EXPECT_EQ(false, GetQuicFlag(FLAGS_foo)); + EXPECT_EQ(123, GetQuicFlag(FLAGS_bar)); + EXPECT_EQ("splash!", GetQuicFlag(FLAGS_baz)); +} + +TEST_F(QuicCommandLineFlagTest, NotSpecified) { + const char* argv[]{"one", "two", "three"}; + auto parse_result = + QuicParseCommandLineFlagsForTest("usage message", base::size(argv), argv); + EXPECT_FALSE(parse_result.exit_status.has_value()); + std::vector<std::string> expected_args{"two", "three"}; + EXPECT_EQ(expected_args, parse_result.non_flag_args); + + EXPECT_EQ(false, GetQuicFlag(FLAGS_foo)); + EXPECT_EQ(123, GetQuicFlag(FLAGS_bar)); + EXPECT_EQ("splash!", GetQuicFlag(FLAGS_baz)); +} + +TEST_F(QuicCommandLineFlagTest, BoolFlag) { + for (const char* s : + {"--foo", "--foo=1", "--foo=t", "--foo=True", "--foo=Y", "--foo=yes"}) { + SetQuicFlag(FLAGS_foo, false); + const char* argv[]{"argv0", s}; + auto parse_result = QuicParseCommandLineFlagsForTest( + "usage message", base::size(argv), argv); + EXPECT_FALSE(parse_result.exit_status.has_value()); + EXPECT_TRUE(parse_result.non_flag_args.empty()); + EXPECT_TRUE(GetQuicFlag(FLAGS_foo)); + } + + for (const char* s : + {"--foo=0", "--foo=f", "--foo=False", "--foo=N", "--foo=no"}) { + SetQuicFlag(FLAGS_foo, true); + const char* argv[]{"argv0", s}; + auto parse_result = QuicParseCommandLineFlagsForTest( + "usage message", base::size(argv), argv); + EXPECT_FALSE(parse_result.exit_status.has_value()); + EXPECT_TRUE(parse_result.non_flag_args.empty()); + EXPECT_FALSE(GetQuicFlag(FLAGS_foo)); + } + + for (const char* s : {"--foo=7", "--foo=abc", "--foo=trueish"}) { + SetQuicFlag(FLAGS_foo, false); + const char* argv[]{"argv0", s}; + + testing::internal::CaptureStderr(); + auto parse_result = QuicParseCommandLineFlagsForTest( + "usage message", base::size(argv), argv); + std::string captured_stderr = testing::internal::GetCapturedStderr(); + + EXPECT_TRUE(parse_result.exit_status.has_value()); + EXPECT_EQ(1, *parse_result.exit_status); + EXPECT_THAT(captured_stderr, + testing::ContainsRegex("Invalid value.*for flag --foo")); + EXPECT_TRUE(parse_result.non_flag_args.empty()); + EXPECT_FALSE(GetQuicFlag(FLAGS_foo)); + } +} + +TEST_F(QuicCommandLineFlagTest, Int32Flag) { + for (const int i : {-1, 0, 100, 38239832}) { + SetQuicFlag(FLAGS_bar, 0); + std::string flag_str = base::StringPrintf("--bar=%d", i); + const char* argv[]{"argv0", flag_str.c_str()}; + auto parse_result = QuicParseCommandLineFlagsForTest( + "usage message", base::size(argv), argv); + EXPECT_FALSE(parse_result.exit_status.has_value()); + EXPECT_TRUE(parse_result.non_flag_args.empty()); + EXPECT_EQ(i, GetQuicFlag(FLAGS_bar)); + } + + for (const char* s : {"--bar", "--bar=a", "--bar=9999999999999"}) { + SetQuicFlag(FLAGS_bar, 0); + const char* argv[]{"argv0", s}; + + testing::internal::CaptureStderr(); + auto parse_result = QuicParseCommandLineFlagsForTest( + "usage message", base::size(argv), argv); + std::string captured_stderr = testing::internal::GetCapturedStderr(); + + EXPECT_TRUE(parse_result.exit_status.has_value()); + EXPECT_EQ(1, *parse_result.exit_status); + EXPECT_THAT(captured_stderr, + testing::ContainsRegex("Invalid value.*for flag --bar")); + EXPECT_TRUE(parse_result.non_flag_args.empty()); + EXPECT_EQ(0, GetQuicFlag(FLAGS_bar)); + } +} + +TEST_F(QuicCommandLineFlagTest, StringFlag) { + { + SetQuicFlag(FLAGS_baz, "whee"); + const char* argv[]{"argv0", "--baz"}; + auto parse_result = QuicParseCommandLineFlagsForTest( + "usage message", base::size(argv), argv); + EXPECT_FALSE(parse_result.exit_status.has_value()); + EXPECT_TRUE(parse_result.non_flag_args.empty()); + EXPECT_EQ("", GetQuicFlag(FLAGS_baz)); + } + + for (const char* s : {"", "12345", "abcdefg"}) { + SetQuicFlag(FLAGS_baz, "qux"); + std::string flag_str = base::StrCat({"--baz=", s}); + const char* argv[]{"argv0", flag_str.c_str()}; + auto parse_result = QuicParseCommandLineFlagsForTest( + "usage message", base::size(argv), argv); + EXPECT_FALSE(parse_result.exit_status.has_value()); + EXPECT_TRUE(parse_result.non_flag_args.empty()); + EXPECT_EQ(s, GetQuicFlag(FLAGS_baz)); + } +} + +TEST_F(QuicCommandLineFlagTest, PrintHelp) { + testing::internal::CaptureStdout(); + QuicPrintCommandLineFlagHelp("usage message"); + std::string captured_stdout = testing::internal::GetCapturedStdout(); + EXPECT_THAT(captured_stdout, testing::HasSubstr("usage message")); + EXPECT_THAT(captured_stdout, + testing::ContainsRegex("--help +Print this help message.")); + EXPECT_THAT(captured_stdout, + testing::ContainsRegex("--foo +An old silent pond...")); + EXPECT_THAT(captured_stdout, + testing::ContainsRegex("--bar +A frog jumps into the pond,")); + EXPECT_THAT(captured_stdout, testing::ContainsRegex("--baz +Silence again.")); +} + class QuicFlagsTest : public QuicTest {}; TEST_F(QuicFlagsTest, SetQuicFlagByName_bool) {
diff --git a/net/quic/quic_http_stream.cc b/net/quic/quic_http_stream.cc index d7e51b1..7aeb0f6 100644 --- a/net/quic/quic_http_stream.cc +++ b/net/quic/quic_http_stream.cc
@@ -110,8 +110,6 @@ return HttpResponseInfo::CONNECTION_INFO_QUIC_RFC_V1; case quic::QUIC_VERSION_RESERVED_FOR_NEGOTIATION: return HttpResponseInfo::CONNECTION_INFO_QUIC_999; - case quic::QUIC_VERSION_IETF_2_DRAFT_01: - return HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_1; } NOTREACHED(); return HttpResponseInfo::CONNECTION_INFO_QUIC_UNKNOWN_VERSION;
diff --git a/net/quic/quic_network_transaction_unittest.cc b/net/quic/quic_network_transaction_unittest.cc index 96c2f7d..843ea5e4 100644 --- a/net/quic/quic_network_transaction_unittest.cc +++ b/net/quic/quic_network_transaction_unittest.cc
@@ -688,25 +688,8 @@ EXPECT_EQ(status_line, response->headers->GetStatusLine()); EXPECT_TRUE(response->was_fetched_via_spdy); EXPECT_TRUE(response->was_alpn_negotiated); - auto connection_info = - QuicHttpStream::ConnectionInfoFromQuicVersion(version); - if (connection_info == response->connection_info) { - return; - } - // QUIC v1 and QUIC v2 are considered a match, because they have the same - // ALPN token. - if ((connection_info == HttpResponseInfo::CONNECTION_INFO_QUIC_RFC_V1 || - connection_info == HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_1) && - (response->connection_info == - HttpResponseInfo::CONNECTION_INFO_QUIC_RFC_V1 || - response->connection_info == - HttpResponseInfo::CONNECTION_INFO_QUIC_2_DRAFT_1)) { - return; - } - - // They do not match. This EXPECT_EQ will fail and print useful - // information. - EXPECT_EQ(connection_info, response->connection_info); + EXPECT_EQ(QuicHttpStream::ConnectionInfoFromQuicVersion(version), + response->connection_info); } void CheckWasQuicResponse(HttpNetworkTransaction* trans, @@ -1019,53 +1002,6 @@ } } - // Verify that the set of QUIC protocols in `alt_svc_info_vector` and - // `supported_versions` is the same. Since QUICv1 and QUICv2 have the same - // ALPN token "h3", they cannot be distinguished when parsing ALPN, so - // consider them equal. This is accomplished by comparing the set of ALPN - // strings (instead of comparing the set of ParsedQuicVersion entities). - static void VerifyQuicVersionsInAlternativeServices( - const AlternativeServiceInfoVector& alt_svc_info_vector, - const quic::ParsedQuicVersionVector& supported_versions) { - // Versions that support the legacy Google-specific Alt-Svc format are sent - // in a single Alt-Svc entry, therefore they are accumulated in a single - // AlternativeServiceInfo, whereas more recent versions all have their own - // Alt-Svc entry and AlternativeServiceInfo entry. Flatten to compare. - std::vector<std::string> alt_svc_negotiated_alpn; - for (const auto& alt_svc_info : alt_svc_info_vector) { - EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol); - for (const auto& version : alt_svc_info.advertised_versions()) { - alt_svc_negotiated_alpn.push_back(quic::AlpnForVersion(version)); - } - } - - // Sort and deduplicate. - std::sort(alt_svc_negotiated_alpn.begin(), alt_svc_negotiated_alpn.end()); - auto last = std::unique(alt_svc_negotiated_alpn.begin(), - alt_svc_negotiated_alpn.end()); - if (last != alt_svc_negotiated_alpn.end()) { - alt_svc_negotiated_alpn.erase(last, alt_svc_negotiated_alpn.end()); - } - - // Process supported versions. - std::vector<std::string> supported_alpn; - for (const auto& version : supported_versions) { - supported_alpn.push_back(quic::AlpnForVersion(version)); - } - - // Sort and deduplicate. - std::sort(supported_alpn.begin(), supported_alpn.end()); - last = std::unique(supported_alpn.begin(), supported_alpn.end()); - if (last != supported_alpn.end()) { - supported_alpn.erase(last, supported_alpn.end()); - } - - // Compare. - ASSERT_EQ(supported_alpn.size(), alt_svc_negotiated_alpn.size()); - EXPECT_TRUE(std::equal(supported_alpn.begin(), supported_alpn.end(), - alt_svc_negotiated_alpn.begin())); - } - const quic::ParsedQuicVersion version_; const bool client_headers_include_h2_stream_dependency_; quic::ParsedQuicVersionVector supported_versions_; @@ -1865,8 +1801,34 @@ alt_svc_info_vector = session_->http_server_properties()->GetAlternativeServiceInfos( server, NetworkIsolationKey()); - VerifyQuicVersionsInAlternativeServices(alt_svc_info_vector, - supported_versions_); + // Versions that support the legacy Google-specific Alt-Svc format are sent in + // a single Alt-Svc entry, therefore they are accumulated in a single + // AlternativeServiceInfo, whereas more recent versions all have their own + // Alt-Svc entry and AlternativeServiceInfo entry. Flatten to compare. + quic::ParsedQuicVersionVector alt_svc_negotiated_versions; + for (const auto& alt_svc_info : alt_svc_info_vector) { + EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol); + for (const auto& version : alt_svc_info.advertised_versions()) { + if (std::find(alt_svc_negotiated_versions.begin(), + alt_svc_negotiated_versions.end(), + version) == alt_svc_negotiated_versions.end()) { + alt_svc_negotiated_versions.push_back(version); + } + } + } + + ASSERT_EQ(supported_versions_.size(), alt_svc_negotiated_versions.size()); + auto version_compare = [](const quic::ParsedQuicVersion& a, + const quic::ParsedQuicVersion& b) { + return std::tie(a.transport_version, a.handshake_protocol) < + std::tie(b.transport_version, b.handshake_protocol); + }; + std::sort(supported_versions_.begin(), supported_versions_.end(), + version_compare); + std::sort(alt_svc_negotiated_versions.begin(), + alt_svc_negotiated_versions.end(), version_compare); + EXPECT_TRUE(std::equal(supported_versions_.begin(), supported_versions_.end(), + alt_svc_negotiated_versions.begin())); } // Regression test for https://crbug.com/546991. @@ -2190,32 +2152,22 @@ } TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceWithVersionForQuic1) { - // Both client and server supports two QUIC versions: - // Client supports |supported_versions_[0]| and |supported_versions_[1]|, - // server supports |version_| and |advertised_version_2|. - // Only |version_| (same as |supported_versions_[0]|) is supported by both. + // Both server advertises and client supports two QUIC versions. + // Only |version_| is advertised and supported. // The QuicStreamFactoy will pick up |version_|, which is verified as the // PacketMakers are using |version_|. - // Compare ALPN strings instead of ParsedQuicVersions because QUIC v1 and v2 - // have the same ALPN string. - ASSERT_EQ(1u, supported_versions_.size()); - ASSERT_EQ(supported_versions_[0], version_); + // Add support for another QUIC version besides |version_| on the client side. + // Also find a different version advertised by the server. quic::ParsedQuicVersion advertised_version_2 = quic::ParsedQuicVersion::Unsupported(); for (const quic::ParsedQuicVersion& version : quic::AllSupportedVersions()) { - if (quic::AlpnForVersion(version) == quic::AlpnForVersion(version_)) { + if (version == version_) continue; - } if (supported_versions_.size() != 2) { supported_versions_.push_back(version); continue; } - if (supported_versions_.size() == 2 && - quic::AlpnForVersion(supported_versions_[1]) == - quic::AlpnForVersion(version)) { - continue; - } advertised_version_2 = version; break; } @@ -2548,8 +2500,34 @@ const AlternativeServiceInfoVector alt_svc_info_vector = session_->http_server_properties()->GetAlternativeServiceInfos( https_server, NetworkIsolationKey()); - VerifyQuicVersionsInAlternativeServices(alt_svc_info_vector, - supported_versions_); + // Versions that support the legacy Google-specific Alt-Svc format are sent in + // a single Alt-Svc entry, therefore they are accumulated in a single + // AlternativeServiceInfo, whereas more recent versions all have their own + // Alt-Svc entry and AlternativeServiceInfo entry. Flatten to compare. + quic::ParsedQuicVersionVector alt_svc_negotiated_versions; + for (const auto& alt_svc_info : alt_svc_info_vector) { + EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol); + for (const auto& version : alt_svc_info.advertised_versions()) { + if (std::find(alt_svc_negotiated_versions.begin(), + alt_svc_negotiated_versions.end(), + version) == alt_svc_negotiated_versions.end()) { + alt_svc_negotiated_versions.push_back(version); + } + } + } + + ASSERT_EQ(supported_versions_.size(), alt_svc_negotiated_versions.size()); + auto version_compare = [](const quic::ParsedQuicVersion& a, + const quic::ParsedQuicVersion& b) { + return std::tie(a.transport_version, a.handshake_protocol) < + std::tie(b.transport_version, b.handshake_protocol); + }; + std::sort(supported_versions_.begin(), supported_versions_.end(), + version_compare); + std::sort(alt_svc_negotiated_versions.begin(), + alt_svc_negotiated_versions.end(), version_compare); + EXPECT_TRUE(std::equal(supported_versions_.begin(), supported_versions_.end(), + alt_svc_negotiated_versions.begin())); } TEST_P(QuicNetworkTransactionTest, UseAlternativeServiceAllSupportedVersion) {
diff --git a/net/quiche/common/platform/impl/quiche_command_line_flags_impl.cc b/net/quiche/common/platform/impl/quiche_command_line_flags_impl.cc deleted file mode 100644 index c996161..0000000 --- a/net/quiche/common/platform/impl/quiche_command_line_flags_impl.cc +++ /dev/null
@@ -1,259 +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 "net/quiche/common/platform/impl/quiche_command_line_flags_impl.h" - -#include <initializer_list> -#include <iostream> -#include <set> -#include <string> -#include <vector> - -#include "base/command_line.h" -#include "base/export_template.h" -#include "base/logging.h" -#include "base/strings/strcat.h" -#include "base/strings/string_number_conversions.h" -#include "base/strings/string_util.h" -#include "base/strings/utf_string_conversions.h" -#include "build/build_config.h" -#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" - -namespace quiche { - -namespace { - -size_t FindLineWrapPosition(const std::string& s, size_t desired_len) { - if (s.length() <= desired_len) { - return std::string::npos; - } - size_t pos = s.find_last_of(base::kWhitespaceASCII, desired_len); - if (pos != std::string::npos) { - return pos; - } - pos = s.find_first_of(base::kWhitespaceASCII, desired_len); - if (pos != std::string::npos) { - return pos; - } - return std::string::npos; -} - -// Pretty-print a flag description in the format: -// -// --flag_name Some text describing the flag that can -// wrap around to the next line. -void AppendFlagDescription(const std::string& name, - std::string help, - std::string* out) { - const int kStartCol = 20; - const int kEndCol = 80; - const int kMinPadding = 2; - static const char kDashes[] = "--"; - - base::StrAppend(out, {kDashes, name}); - int col = strlen(kDashes) + name.length(); - if (col + kMinPadding < kEndCol) { - // Start help text on same line - int pad_len = std::max(kMinPadding, kStartCol - col); - base::StrAppend(out, {std::string(pad_len, ' ')}); - col += pad_len; - } else { - // Start help text on next line - base::StrAppend(out, {"\n", std::string(kStartCol, ' ')}); - col = kStartCol; - } - - while (!help.empty()) { - size_t desired_len = kEndCol - col; - size_t wrap_pos = FindLineWrapPosition(help, desired_len); - if (wrap_pos == std::string::npos) { - base::StrAppend(out, {help}); - break; - } - base::StrAppend( - out, {help.substr(0, wrap_pos), "\n", std::string(kStartCol, ' ')}); - help = help.substr(wrap_pos + 1); - col = kStartCol; - } - base::StrAppend(out, {"\n"}); -} - -// Overload for platforms where base::CommandLine::StringType == std::string. -[[maybe_unused]] std::vector<std::string> ToQuicheStringVector( - const std::vector<std::string>& v) { - return v; -} - -#if defined(WCHAR_T_IS_UTF16) -// Overload for platforms where base::CommandLine::StringType == std::wstring. -[[maybe_unused]] std::vector<std::string> ToQuicheStringVector( - const std::vector<std::wstring>& v) { - std::vector<std::string> qsv; - for (const auto& s : v) { - if (!base::IsStringASCII(s)) { - QUIC_LOG(ERROR) << "Unable to convert to ASCII: " << s; - continue; - } - qsv.push_back(base::WideToASCII(s)); - } - return qsv; -} -#endif // defined(WCHAR_T_IS_UTF16) - -} // namespace - -// static -QuicheFlagRegistry& QuicheFlagRegistry::GetInstance() { - static base::NoDestructor<QuicheFlagRegistry> instance; - return *instance; -} - -void QuicheFlagRegistry::RegisterFlag( - const char* name, - std::unique_ptr<QuicheFlagHelper> helper) { - flags_.emplace(std::string(name), std::move(helper)); -} - -bool QuicheFlagRegistry::SetFlags(const base::CommandLine& command_line, - std::string* error_msg) const { - for (const auto& kv : flags_) { - const std::string& name = kv.first; - const QuicheFlagHelper* helper = kv.second.get(); - if (!command_line.HasSwitch(name)) { - continue; - } - std::string value = command_line.GetSwitchValueASCII(name); - if (!helper->SetFlag(value)) { - *error_msg = - base::StrCat({"Invalid value \"", value, "\" for flag --", name}); - return false; - } - QUIC_LOG(INFO) << "Set flag --" << name << " = " << value; - } - return true; -} - -void QuicheFlagRegistry::ResetFlags() const { - for (const auto& kv : flags_) { - kv.second->ResetFlag(); - QUIC_LOG(INFO) << "Reset flag --" << kv.first; - } -} - -std::string QuicheFlagRegistry::GetHelp() const { - std::string help; - AppendFlagDescription("help", "Print this help message.", &help); - for (const auto& kv : flags_) { - AppendFlagDescription(kv.first, kv.second->GetHelp(), &help); - } - return help; -} - -template <> -bool TypedQuicheFlagHelper<bool>::SetFlag(const std::string& s) const { - static const base::NoDestructor<std::set<std::string>> kTrueValues( - std::initializer_list<std::string>({"", "1", "t", "true", "y", "yes"})); - static const base::NoDestructor<std::set<std::string>> kFalseValues( - std::initializer_list<std::string>({"0", "f", "false", "n", "no"})); - if (kTrueValues->find(base::ToLowerASCII(s)) != kTrueValues->end()) { - *flag_ = true; - return true; - } - if (kFalseValues->find(base::ToLowerASCII(s)) != kFalseValues->end()) { - *flag_ = false; - return true; - } - return false; -} - -template <> -bool TypedQuicheFlagHelper<uint16_t>::SetFlag(const std::string& s) const { - int value; - if (!base::StringToInt(s, &value) || - value < std::numeric_limits<uint16_t>::min() || - value > std::numeric_limits<uint16_t>::max()) { - return false; - } - *flag_ = static_cast<uint16_t>(value); - return true; -} - -template <> -bool TypedQuicheFlagHelper<int32_t>::SetFlag(const std::string& s) const { - int32_t value; - if (!base::StringToInt(s, &value)) { - return false; - } - *flag_ = value; - return true; -} - -template <> -bool TypedQuicheFlagHelper<std::string>::SetFlag(const std::string& s) const { - *flag_ = s; - return true; -} - -template class EXPORT_TEMPLATE_DEFINE(QUICHE_EXPORT_PRIVATE) - TypedQuicheFlagHelper<bool>; -template class EXPORT_TEMPLATE_DEFINE(QUICHE_EXPORT_PRIVATE) - TypedQuicheFlagHelper<uint16_t>; -template class EXPORT_TEMPLATE_DEFINE(QUICHE_EXPORT_PRIVATE) - TypedQuicheFlagHelper<int32_t>; -template class EXPORT_TEMPLATE_DEFINE(QUICHE_EXPORT_PRIVATE) - TypedQuicheFlagHelper<std::string>; - -QuicheFlagRegistry::QuicheFlagRegistry() = default; -QuicheFlagRegistry::~QuicheFlagRegistry() = default; - -std::vector<std::string> QuicheParseCommandLineFlagsImpl( - const char* usage, - int argc, - const char* const* argv) { - base::CommandLine::Init(argc, argv); - auto result = QuicheParseCommandLineFlagsHelper( - usage, *base::CommandLine::ForCurrentProcess()); - if (result.exit_status.has_value()) { - exit(*result.exit_status); - } - - logging::LoggingSettings settings; - settings.logging_dest = logging::LOG_TO_STDERR; - CHECK(logging::InitLogging(settings)); - - return result.non_flag_args; -} - -QuicheParseCommandLineFlagsResult QuicheParseCommandLineFlagsHelper( - const char* usage, - const base::CommandLine& command_line) { - QuicheParseCommandLineFlagsResult result; - result.non_flag_args = ToQuicheStringVector(command_line.GetArgs()); - if (command_line.HasSwitch("h") || command_line.HasSwitch("help")) { - QuichePrintCommandLineFlagHelpImpl(usage); - result.exit_status = 0; - } else { - std::string msg; - if (!QuicheFlagRegistry::GetInstance().SetFlags(command_line, &msg)) { - std::cerr << msg << std::endl; - result.exit_status = 1; - } - } - return result; -} - -void QuichePrintCommandLineFlagHelpImpl(const char* usage) { - std::cout << usage << std::endl - << "Options:" << std::endl - << QuicheFlagRegistry::GetInstance().GetHelp() << std::endl; -} - -QuicheParseCommandLineFlagsResult::QuicheParseCommandLineFlagsResult() = - default; -QuicheParseCommandLineFlagsResult::QuicheParseCommandLineFlagsResult( - const QuicheParseCommandLineFlagsResult&) = default; -QuicheParseCommandLineFlagsResult::~QuicheParseCommandLineFlagsResult() = - default; - -} // namespace quiche
diff --git a/net/quiche/common/platform/impl/quiche_command_line_flags_impl.h b/net/quiche/common/platform/impl/quiche_command_line_flags_impl.h deleted file mode 100644 index bdc5bf8b..0000000 --- a/net/quiche/common/platform/impl/quiche_command_line_flags_impl.h +++ /dev/null
@@ -1,158 +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 NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_COMMAND_LINE_FLAGS_IMPL_H_ -#define NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_COMMAND_LINE_FLAGS_IMPL_H_ - -#include <string> -#include <vector> - -#include "base/command_line.h" -#include "base/export_template.h" -#include "base/memory/raw_ptr.h" -#include "base/no_destructor.h" -#include "net/third_party/quiche/src/common/platform/api/quiche_export.h" -#include "net/third_party/quiche/src/common/platform/api/quiche_flags.h" -#include "third_party/abseil-cpp/absl/types/optional.h" - -namespace quiche { - -// Abstract class for setting flags and fetching help strings. -class QuicheFlagHelper { - public: - explicit QuicheFlagHelper(const char* help) : help_(help) {} - virtual ~QuicheFlagHelper() = default; - - virtual bool SetFlag(const std::string& value) const = 0; - virtual void ResetFlag() const = 0; - std::string GetHelp() const { return help_; } - - private: - std::string help_; -}; - -// Templated class for setting flags of various types. -template <typename T> -class TypedQuicheFlagHelper : public QuicheFlagHelper { - public: - TypedQuicheFlagHelper(T* flag, const T& default_value, const char* help) - : QuicheFlagHelper(help), flag_(flag), default_value_(default_value) {} - bool SetFlag(const std::string& value) const override; - void ResetFlag() const override { *flag_ = default_value_; } - - private: - mutable raw_ptr<T> flag_; - T default_value_; -}; - -// SetFlag specializations. Implementations in .cc file. -template <> -QUICHE_EXPORT_PRIVATE bool TypedQuicheFlagHelper<bool>::SetFlag( - const std::string&) const; -template <> -QUICHE_EXPORT_PRIVATE bool TypedQuicheFlagHelper<uint16_t>::SetFlag( - const std::string&) const; -template <> -QUICHE_EXPORT_PRIVATE bool TypedQuicheFlagHelper<int32_t>::SetFlag( - const std::string&) const; -template <> -QUICHE_EXPORT_PRIVATE bool TypedQuicheFlagHelper<std::string>::SetFlag( - const std::string&) const; - -// TypedQuicheFlagHelper instantiations are in .cc file. -extern template class EXPORT_TEMPLATE_DECLARE(QUICHE_EXPORT_PRIVATE) - TypedQuicheFlagHelper<bool>; -extern template class EXPORT_TEMPLATE_DECLARE(QUICHE_EXPORT_PRIVATE) - TypedQuicheFlagHelper<uint16_t>; -extern template class EXPORT_TEMPLATE_DECLARE(QUICHE_EXPORT_PRIVATE) - TypedQuicheFlagHelper<int32_t>; -extern template class EXPORT_TEMPLATE_DECLARE(QUICHE_EXPORT_PRIVATE) - TypedQuicheFlagHelper<std::string>; - -// Registry of QuicheFlagHelpers. -class QUICHE_EXPORT_PRIVATE QuicheFlagRegistry { - public: - ~QuicheFlagRegistry(); - - static QuicheFlagRegistry& GetInstance(); - - // Adds a flag to the registry. - void RegisterFlag(const char* name, std::unique_ptr<QuicheFlagHelper> helper); - - // Sets any flags in the registry that are specified in |command_line|, - // returning true iff successful. If there is a failure, e.g. due to an - // invalid flag value, returns false and sets |error_msg|. - bool SetFlags(const base::CommandLine& command_line, - std::string* error_msg) const; - - // Resets flags to their default values. - void ResetFlags() const; - - // Returns a help string consisting of the names and help strings of all - // registered flags. - std::string GetHelp() const; - - private: - friend class base::NoDestructor<QuicheFlagRegistry>; - - // Should only be accessed as a singleton. - QuicheFlagRegistry(); - - std::map<std::string, std::unique_ptr<QuicheFlagHelper>> flags_; -}; - -// Class instantiated in DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL macro expansion, -// that registers flag as a side effect of its constructor. Similar in spirit to -// absl::flags_internal::FlagRegistrar. -template <typename T> -class QuicheFlagSetup { - public: - QuicheFlagSetup(T* flag, - const char* name, - const T& default_value, - const char* help) { - QuicheFlagRegistry::GetInstance().RegisterFlag( - name, - std::make_unique<TypedQuicheFlagHelper<T>>(flag, default_value, help)); - } - // Allow QuicheFlagSetup instance to convert to a bool in - // DEFINE_QUIC_COMMAND_LINE_FLAG_IMPL macro expansion, so it can go away. - operator bool() const { return true; } -}; - -// ------------------------------------------------------------------------ -// DEFINE_QUICHE_COMMAND_LINE_FLAG implementation. -// ------------------------------------------------------------------------ - -#define DEFINE_QUICHE_COMMAND_LINE_FLAG_IMPL(type, name, default_value, help) \ - type FLAGS_##name = default_value; \ - bool FLAGS_no##name = \ - quiche::QuicheFlagSetup<type>(&FLAGS_##name, #name, default_value, help) - -QUICHE_EXPORT_PRIVATE std::vector<std::string> QuicheParseCommandLineFlagsImpl( - const char* usage, - int argc, - const char* const* argv); - -// Used internally by QuicheParseCommandLineFlagsImpl(), but exposed here for -// testing. -struct QUICHE_EXPORT_PRIVATE QuicheParseCommandLineFlagsResult { - QuicheParseCommandLineFlagsResult(); - QuicheParseCommandLineFlagsResult(const QuicheParseCommandLineFlagsResult&); - ~QuicheParseCommandLineFlagsResult(); - - std::vector<std::string> non_flag_args; - absl::optional<int> exit_status; -}; - -QUICHE_EXPORT_PRIVATE QuicheParseCommandLineFlagsResult -QuicheParseCommandLineFlagsHelper(const char* usage, - const base::CommandLine& command_line); - -QUICHE_EXPORT_PRIVATE void QuichePrintCommandLineFlagHelpImpl( - const char* usage); - -} // namespace quiche - -#endif // NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_COMMAND_LINE_FLAGS_IMPL_H_
diff --git a/net/quiche/common/platform/impl/quiche_command_line_flags_test.cc b/net/quiche/common/platform/impl/quiche_command_line_flags_test.cc deleted file mode 100644 index 056922e1..0000000 --- a/net/quiche/common/platform/impl/quiche_command_line_flags_test.cc +++ /dev/null
@@ -1,188 +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/quiche/src/common/platform/api/quiche_command_line_flags.h" - -#include <string> - -#include "base/command_line.h" -#include "base/cxx17_backports.h" -#include "base/strings/strcat.h" -#include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "net/third_party/quiche/src/common/platform/api/quiche_command_line_flags.h" -#include "net/third_party/quiche/src/common/platform/api/quiche_test.h" -#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h" - -DEFINE_QUICHE_COMMAND_LINE_FLAG(bool, foo, false, "An old silent pond..."); -DEFINE_QUICHE_COMMAND_LINE_FLAG(int32_t, - bar, - 123, - "A frog jumps into the pond,"); -DEFINE_QUICHE_COMMAND_LINE_FLAG(std::string, baz, "splash!", "Silence again."); - -namespace quiche::test { - -class QuicheCommandLineFlagTest : public QuicheTest { - protected: - void SetUp() override { QuicheFlagRegistry::GetInstance().ResetFlags(); } - - static QuicheParseCommandLineFlagsResult QuicheParseCommandLineFlagsForTest( - const char* usage, - int argc, - const char* const* argv) { - base::CommandLine::StringVector v; - FillCommandLineArgs(argc, argv, &v); - return QuicheParseCommandLineFlagsHelper(usage, base::CommandLine(v)); - } - - private: - // Overload for platforms where base::CommandLine::StringType == std::string. - static void FillCommandLineArgs(int argc, - const char* const* argv, - std::vector<std::string>* v) { - for (int i = 0; i < argc; ++i) { - v->push_back(argv[i]); - } - } - - // Overload for platforms where base::CommandLine::StringType == - // std::u16string. - static void FillCommandLineArgs(int argc, - const char* const* argv, - std::vector<std::u16string>* v) { - for (int i = 0; i < argc; ++i) { - v->push_back(base::UTF8ToUTF16(argv[i])); - } - } -}; - -TEST_F(QuicheCommandLineFlagTest, DefaultValues) { - EXPECT_EQ(false, GetQuicheFlag(FLAGS_foo)); - EXPECT_EQ(123, GetQuicheFlag(FLAGS_bar)); - EXPECT_EQ("splash!", GetQuicheFlag(FLAGS_baz)); -} - -TEST_F(QuicheCommandLineFlagTest, NotSpecified) { - const char* argv[]{"one", "two", "three"}; - auto parse_result = QuicheParseCommandLineFlagsForTest( - "usage message", base::size(argv), argv); - EXPECT_FALSE(parse_result.exit_status.has_value()); - std::vector<std::string> expected_args{"two", "three"}; - EXPECT_EQ(expected_args, parse_result.non_flag_args); - - EXPECT_EQ(false, GetQuicheFlag(FLAGS_foo)); - EXPECT_EQ(123, GetQuicheFlag(FLAGS_bar)); - EXPECT_EQ("splash!", GetQuicheFlag(FLAGS_baz)); -} - -TEST_F(QuicheCommandLineFlagTest, BoolFlag) { - for (const char* s : - {"--foo", "--foo=1", "--foo=t", "--foo=True", "--foo=Y", "--foo=yes"}) { - SetQuicheFlag(FLAGS_foo, false); - const char* argv[]{"argv0", s}; - auto parse_result = QuicheParseCommandLineFlagsForTest( - "usage message", base::size(argv), argv); - EXPECT_FALSE(parse_result.exit_status.has_value()); - EXPECT_TRUE(parse_result.non_flag_args.empty()); - EXPECT_TRUE(GetQuicheFlag(FLAGS_foo)); - } - - for (const char* s : - {"--foo=0", "--foo=f", "--foo=False", "--foo=N", "--foo=no"}) { - SetQuicheFlag(FLAGS_foo, true); - const char* argv[]{"argv0", s}; - auto parse_result = QuicheParseCommandLineFlagsForTest( - "usage message", base::size(argv), argv); - EXPECT_FALSE(parse_result.exit_status.has_value()); - EXPECT_TRUE(parse_result.non_flag_args.empty()); - EXPECT_FALSE(GetQuicheFlag(FLAGS_foo)); - } - - for (const char* s : {"--foo=7", "--foo=abc", "--foo=trueish"}) { - SetQuicheFlag(FLAGS_foo, false); - const char* argv[]{"argv0", s}; - - testing::internal::CaptureStderr(); - auto parse_result = QuicheParseCommandLineFlagsForTest( - "usage message", base::size(argv), argv); - std::string captured_stderr = testing::internal::GetCapturedStderr(); - - EXPECT_TRUE(parse_result.exit_status.has_value()); - EXPECT_EQ(1, *parse_result.exit_status); - EXPECT_THAT(captured_stderr, - testing::ContainsRegex("Invalid value.*for flag --foo")); - EXPECT_TRUE(parse_result.non_flag_args.empty()); - EXPECT_FALSE(GetQuicheFlag(FLAGS_foo)); - } -} - -TEST_F(QuicheCommandLineFlagTest, Int32Flag) { - for (const int i : {-1, 0, 100, 38239832}) { - SetQuicheFlag(FLAGS_bar, 0); - std::string flag_str = base::StringPrintf("--bar=%d", i); - const char* argv[]{"argv0", flag_str.c_str()}; - auto parse_result = QuicheParseCommandLineFlagsForTest( - "usage message", base::size(argv), argv); - EXPECT_FALSE(parse_result.exit_status.has_value()); - EXPECT_TRUE(parse_result.non_flag_args.empty()); - EXPECT_EQ(i, GetQuicheFlag(FLAGS_bar)); - } - - for (const char* s : {"--bar", "--bar=a", "--bar=9999999999999"}) { - SetQuicheFlag(FLAGS_bar, 0); - const char* argv[]{"argv0", s}; - - testing::internal::CaptureStderr(); - auto parse_result = QuicheParseCommandLineFlagsForTest( - "usage message", base::size(argv), argv); - std::string captured_stderr = testing::internal::GetCapturedStderr(); - - EXPECT_TRUE(parse_result.exit_status.has_value()); - EXPECT_EQ(1, *parse_result.exit_status); - EXPECT_THAT(captured_stderr, - testing::ContainsRegex("Invalid value.*for flag --bar")); - EXPECT_TRUE(parse_result.non_flag_args.empty()); - EXPECT_EQ(0, GetQuicheFlag(FLAGS_bar)); - } -} - -TEST_F(QuicheCommandLineFlagTest, StringFlag) { - { - SetQuicheFlag(FLAGS_baz, "whee"); - const char* argv[]{"argv0", "--baz"}; - auto parse_result = QuicheParseCommandLineFlagsForTest( - "usage message", base::size(argv), argv); - EXPECT_FALSE(parse_result.exit_status.has_value()); - EXPECT_TRUE(parse_result.non_flag_args.empty()); - EXPECT_EQ("", GetQuicheFlag(FLAGS_baz)); - } - - for (const char* s : {"", "12345", "abcdefg"}) { - SetQuicheFlag(FLAGS_baz, "qux"); - std::string flag_str = base::StrCat({"--baz=", s}); - const char* argv[]{"argv0", flag_str.c_str()}; - auto parse_result = QuicheParseCommandLineFlagsForTest( - "usage message", base::size(argv), argv); - EXPECT_FALSE(parse_result.exit_status.has_value()); - EXPECT_TRUE(parse_result.non_flag_args.empty()); - EXPECT_EQ(s, GetQuicheFlag(FLAGS_baz)); - } -} - -TEST_F(QuicheCommandLineFlagTest, PrintHelp) { - testing::internal::CaptureStdout(); - QuichePrintCommandLineFlagHelp("usage message"); - std::string captured_stdout = testing::internal::GetCapturedStdout(); - EXPECT_THAT(captured_stdout, testing::HasSubstr("usage message")); - EXPECT_THAT(captured_stdout, - testing::ContainsRegex("--help +Print this help message.")); - EXPECT_THAT(captured_stdout, - testing::ContainsRegex("--foo +An old silent pond...")); - EXPECT_THAT(captured_stdout, - testing::ContainsRegex("--bar +A frog jumps into the pond,")); - EXPECT_THAT(captured_stdout, testing::ContainsRegex("--baz +Silence again.")); -} - -} // namespace quiche::test
diff --git a/net/tools/quic/quic_simple_client_bin.cc b/net/tools/quic/quic_simple_client_bin.cc index 9233b80..3f09694c8 100644 --- a/net/tools/quic/quic_simple_client_bin.cc +++ b/net/tools/quic/quic_simple_client_bin.cc
@@ -36,7 +36,6 @@ #include "base/logging.h" #include "net/base/net_errors.h" #include "net/quic/address_utils.h" -#include "net/third_party/quiche/src/common/platform/api/quiche_command_line_flags.h" #include "net/third_party/quiche/src/quic/core/quic_error_codes.h" #include "net/third_party/quiche/src/quic/core/quic_packets.h" #include "net/third_party/quiche/src/quic/core/quic_server_id.h" @@ -92,9 +91,9 @@ // All non-flag arguments should be interpreted as URLs to fetch. std::vector<std::string> urls = - quiche::QuicheParseCommandLineFlags(usage, argc, argv); + quic::QuicParseCommandLineFlags(usage, argc, argv); if (urls.size() != 1) { - quiche::QuichePrintCommandLineFlagHelp(usage); + quic::QuicPrintCommandLineFlagHelp(usage); exit(0); }
diff --git a/net/tools/quic/quic_simple_server_backend_factory.cc b/net/tools/quic/quic_simple_server_backend_factory.cc index 9ee3df7..364b7101 100644 --- a/net/tools/quic/quic_simple_server_backend_factory.cc +++ b/net/tools/quic/quic_simple_server_backend_factory.cc
@@ -3,18 +3,17 @@ // found in the LICENSE file. #include "net/tools/quic/quic_simple_server_backend_factory.h" -#include "net/third_party/quiche/src/common/platform/api/quiche_command_line_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/tools/quic/quic_http_proxy_backend_stream.h" -DEFINE_QUICHE_COMMAND_LINE_FLAG( +DEFINE_QUIC_COMMAND_LINE_FLAG( std::string, quic_mode, "cache", "Specifies the mode for the server to operate in. Either " "'cache' or 'proxy'"); -DEFINE_QUICHE_COMMAND_LINE_FLAG( +DEFINE_QUIC_COMMAND_LINE_FLAG( std::string, quic_proxy_backend_url, "",
diff --git a/net/tools/quic/quic_simple_server_bin.cc b/net/tools/quic/quic_simple_server_bin.cc index c9205c0..c903d7d3 100644 --- a/net/tools/quic/quic_simple_server_bin.cc +++ b/net/tools/quic/quic_simple_server_bin.cc
@@ -7,7 +7,6 @@ #include <vector> -#include "net/third_party/quiche/src/common/platform/api/quiche_command_line_flags.h" #include "net/third_party/quiche/src/quic/core/quic_versions.h" #include "net/third_party/quiche/src/quic/platform/api/quic_flags.h" #include "net/third_party/quiche/src/quic/platform/api/quic_system_event_loop.h" @@ -35,9 +34,9 @@ QuicSystemEventLoop event_loop("quic_server"); const char* usage = "Usage: quic_server [options]"; std::vector<std::string> non_option_args = - quiche::QuicheParseCommandLineFlags(usage, argc, argv); + quic::QuicParseCommandLineFlags(usage, argc, argv); if (!non_option_args.empty()) { - quiche::QuichePrintCommandLineFlagHelp(usage); + quic::QuicPrintCommandLineFlagHelp(usage); exit(0); }
diff --git a/sandbox/linux/services/credentials.cc b/sandbox/linux/services/credentials.cc index ca6b5954..c933eafd 100644 --- a/sandbox/linux/services/credentials.cc +++ b/sandbox/linux/services/credentials.cc
@@ -100,7 +100,10 @@ // TODO(crbug.com/1247458) Broken in MSan builds after LLVM f1bb30a4956f. clone_flags |= CLONE_VM | CLONE_VFORK | CLONE_SETTLS; - char tls_buf[PTHREAD_STACK_MIN] = {0}; + // PTHREAD_STACK_MIN can be dynamic in glibc2.34+, so it is not possible to + // zeroify tls_buf assigning { 0 } + char tls_buf[PTHREAD_STACK_MIN]; + memset(tls_buf, 0, PTHREAD_STACK_MIN); tls = tls_buf; #endif
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc index df55e69f..7597cba 100644 --- a/services/network/url_loader.cc +++ b/services/network/url_loader.cc
@@ -349,11 +349,6 @@ continue; } - // TODO(crbug.com/1286857): `Sec-CH-UA-Full` client hint isn't yet in - // request, which trigger a restart, will add in following CL. - if (hint == mojom::WebClientHintsType::kFullUserAgent) { - continue; - } // TODO(crbug.com/1225444): `Sec-CH-Partitioned-Cookies` client hint isn't // yet in the request, so we skip over it to avoid triggering a restart. // Remove this line when support is added for `Sec-CH-Partitioned-Cookies`.
diff --git a/services/preferences/public/cpp/dictionary_value_update.h b/services/preferences/public/cpp/dictionary_value_update.h index 5d96be8..a4b7730 100644 --- a/services/preferences/public/cpp/dictionary_value_update.h +++ b/services/preferences/public/cpp/dictionary_value_update.h
@@ -10,7 +10,6 @@ #include <vector> #include "base/callback.h" -#include "base/memory/raw_ptr.h" #include "base/strings/string_piece.h" #include "services/preferences/public/cpp/scoped_pref_update.h" @@ -157,7 +156,9 @@ const std::vector<base::StringPiece>& path); UpdateCallback report_update_; - const raw_ptr<base::DictionaryValue> value_; + // `value_` is not a raw_ptr<...> for performance reasons (based on analysis + // of sampling profiler data). + base::DictionaryValue* const value_; const std::vector<std::string> path_; };
diff --git a/services/preferences/public/cpp/scoped_pref_update.h b/services/preferences/public/cpp/scoped_pref_update.h index 7da5c34..64fc819b 100644 --- a/services/preferences/public/cpp/scoped_pref_update.h +++ b/services/preferences/public/cpp/scoped_pref_update.h
@@ -10,7 +10,6 @@ #include <string> #include <vector> -#include "base/memory/raw_ptr.h" #include "base/strings/string_piece.h" class PrefService; @@ -62,7 +61,9 @@ void RecordPath(const std::vector<std::string>& path); // Weak pointer. - const raw_ptr<PrefService> service_; + // `service_` is not a raw_ptr<...> for performance reasons (based on analysis + // of sampling profiler data). + PrefService* const service_; // Path of the preference being updated. const std::string path_;
diff --git a/skia/BUILD.gn b/skia/BUILD.gn index 6cc13d93..9cfdc08 100644 --- a/skia/BUILD.gn +++ b/skia/BUILD.gn
@@ -525,11 +525,11 @@ ":skia_core_and_effects", ] if (skia_use_dawn) { - public_deps += [ "//third_party/dawn/src/dawn:dawncpp_headers" ] + public_deps += [ "//third_party/dawn/include/dawn:cpp_headers" ] deps += [ - "//third_party/dawn/src/dawn:dawn_proc", - "//third_party/dawn/src/dawn:dawncpp", - "//third_party/dawn/src/dawn_native", + "//third_party/dawn/src/dawn:cpp", + "//third_party/dawn/src/dawn:proc", + "//third_party/dawn/src/dawn/native", ] } @@ -672,7 +672,7 @@ deps = [ "//gpu/config:workaround_list" ] } if (skia_use_dawn) { - deps += [ "//third_party/dawn/src/dawn:dawncpp_headers" ] + deps += [ "//third_party/dawn/include/dawn:cpp_headers" ] } visibility = [ ":skia" ] @@ -829,7 +829,7 @@ ] deps = [ "//gpu/config:workaround_list" ] if (skia_use_dawn) { - deps += [ "//third_party/dawn/src/dawn:dawncpp_headers" ] + deps += [ "//third_party/dawn/include/dawn:cpp_headers" ] } } }
diff --git a/sql/sandboxed_vfs.cc b/sql/sandboxed_vfs.cc index a1e7d7c..c9de8f7 100644 --- a/sql/sandboxed_vfs.cc +++ b/sql/sandboxed_vfs.cc
@@ -116,6 +116,33 @@ return base::Time::FromJsTime(-kUnixEpochAsJulianDay * kMicroSecondsPerDay); } +#if DCHECK_IS_ON() +// `full_path_cstr` must be a filename argument passed to the VFS from SQLite. +SandboxedVfsFileType VfsFileTypeFromPath(const char* full_path_cstr) { + base::StringPiece full_path(full_path_cstr); + + const char* database_file_cstr = sqlite3_filename_database(full_path_cstr); + base::StringPiece database_file(database_file_cstr); + if (full_path == database_file) + return SandboxedVfsFileType::kDatabase; + + const char* journal_file_cstr = sqlite3_filename_journal(full_path_cstr); + base::StringPiece journal_file(journal_file_cstr); + if (full_path == journal_file) + return SandboxedVfsFileType::kJournal; + + const char* wal_file_cstr = sqlite3_filename_wal(full_path_cstr); + base::StringPiece wal_file(wal_file_cstr); + if (full_path == wal_file) + return SandboxedVfsFileType::kWal; + + NOTREACHED() + << "Argument is not a file name buffer passed from SQLite to a VFS: " + << full_path; + return SandboxedVfsFileType::kDatabase; +} +#endif // DCHECK_IS_ON() + } // namespace // static @@ -149,8 +176,11 @@ return Open(full_path, result_file, new_flags, granted_flags); } - SandboxedVfsFile::Create(std::move(file), std::move(file_path), this, - result_file); + SandboxedVfsFile::Create(std::move(file), std::move(file_path), +#if DCHECK_IS_ON() + VfsFileTypeFromPath(full_path), +#endif // DCHECK_IS_ON() + this, result_file); if (granted_flags) *granted_flags = requested_flags; return SQLITE_OK;
diff --git a/sql/sandboxed_vfs_file.cc b/sql/sandboxed_vfs_file.cc index 0291198..2cb0655 100644 --- a/sql/sandboxed_vfs_file.cc +++ b/sql/sandboxed_vfs_file.cc
@@ -11,6 +11,8 @@ #include "base/check_op.h" #include "base/files/file.h" +#include "base/files/file_path.h" +#include "base/logging.h" #include "base/notreached.h" #include "base/threading/platform_thread.h" #include "build/build_config.h" @@ -129,12 +131,19 @@ // static void SandboxedVfsFile::Create(base::File file, base::FilePath file_path, +#if DCHECK_IS_ON() + SandboxedVfsFileType file_type, +#endif // DCHECK_IS_ON() SandboxedVfs* vfs, sqlite3_file& buffer) { SandboxedVfsFileSqliteBridge& bridge = SandboxedVfsFileSqliteBridge::FromSqliteFile(buffer); bridge.sandboxed_vfs_file = - new SandboxedVfsFile(std::move(file), std::move(file_path), vfs); + new SandboxedVfsFile(std::move(file), std::move(file_path), +#if DCHECK_IS_ON() + file_type, +#endif // DCHECK_IS_ON() + vfs); bridge.sqlite_file.pMethods = GetSqliteIoMethods(); } @@ -154,6 +163,21 @@ DCHECK(buffer); DCHECK_GE(size, 0); DCHECK_GE(offset, 0); + +#if DCHECK_IS_ON() + constexpr int kSqliteDatabaseHeaderOffset = 0; + constexpr int kSqliteDatabaseHeaderSize = 100; + // SQLite's locking protocol only acquires locks on the database file. The + // journal and the WAL file are always unlocked. Also, as an optimization, + // SQLite first reads the database header without locking the file. + DCHECK(sqlite_lock_mode_ > SQLITE_LOCK_NONE || + file_type_ != SandboxedVfsFileType::kDatabase || + (offset == kSqliteDatabaseHeaderOffset && + size == kSqliteDatabaseHeaderSize)) + << "Read from database file with lock mode " << sqlite_lock_mode_ + << "of size" << size << " at offset " << offset; +#endif // DCHECK_IS_ON() + char* data = reinterpret_cast<char*>(buffer); // If we supported mmap()ed files, we'd check for a memory mapping here, @@ -192,6 +216,15 @@ DCHECK(buffer); DCHECK_GE(size, 0); DCHECK_GE(offset, 0); + +#if DCHECK_IS_ON() + // SQLite's locking protocol only acquires locks on the database file. The + // journal and the WAL file are always unlocked. + DCHECK(sqlite_lock_mode_ == SQLITE_LOCK_EXCLUSIVE || + file_type_ != SandboxedVfsFileType::kDatabase) + << "Write to database file with lock mode " << sqlite_lock_mode_; +#endif // DCHECK_IS_ON() + const char* data = reinterpret_cast<const char*>(buffer); // If we supported mmap()ed files, we'd check for a memory mapping here, @@ -286,6 +319,10 @@ } // namespace int SandboxedVfsFile::Lock(int mode) { + DCHECK_GE(mode, sqlite_lock_mode_) + << "SQLite asked the VFS to lock the file up to mode " << mode + << " but the file is already locked at mode " << sqlite_lock_mode_; + #if BUILDFLAG(IS_FUCHSIA) return SQLITE_IOERR_LOCK; #else @@ -360,6 +397,10 @@ } int SandboxedVfsFile::Unlock(int mode) { + DCHECK_LE(mode, sqlite_lock_mode_) + << "SQLite asked the VFS to unlock the file down to mode " << mode + << " but the file is already at mode " << sqlite_lock_mode_; + // No-op if we're already unlocked or at the requested mode. if (sqlite_lock_mode_ == mode || sqlite_lock_mode_ == SQLITE_LOCK_NONE) return SQLITE_OK; @@ -535,11 +576,18 @@ SandboxedVfsFile::SandboxedVfsFile(base::File file, base::FilePath file_path, +#if DCHECK_IS_ON() + SandboxedVfsFileType file_type, +#endif // DCHECK_IS_ON() SandboxedVfs* vfs) : file_(std::move(file)), sqlite_lock_mode_(SQLITE_LOCK_NONE), vfs_(vfs), - file_path_(std::move(file_path)) {} +#if DCHECK_IS_ON() + file_type_(file_type), +#endif // DCHECK_IS_ON() + file_path_(std::move(file_path)) { +} SandboxedVfsFile::~SandboxedVfsFile() = default;
diff --git a/sql/sandboxed_vfs_file.h b/sql/sandboxed_vfs_file.h index 59039a0..8a6293c 100644 --- a/sql/sandboxed_vfs_file.h +++ b/sql/sandboxed_vfs_file.h
@@ -12,6 +12,18 @@ namespace sql { +// The file types associated with a SQLite database. +enum class SandboxedVfsFileType { + // The main file, which stores the database pages. + kDatabase, + // The transaction rollback journal file. Used when WAL is off. + // This file has the same path as the database, plus the "-journal" suffix. + kJournal, + // The Write-Ahead Log (WAL) file. + // This file has the same path as the database, plus the "-wal" suffix. + kWal, +}; + class SandboxedVfs; // SQLite VFS file implementation that works in a sandboxed process. @@ -36,6 +48,9 @@ // returned sqlite3_file object. static void Create(base::File file, base::FilePath file_path, +#if DCHECK_IS_ON() + SandboxedVfsFileType file_type, +#endif // DCHECK_IS_ON() SandboxedVfs* vfs, sqlite3_file& buffer); @@ -68,6 +83,9 @@ private: SandboxedVfsFile(base::File file, base::FilePath file_path, +#if DCHECK_IS_ON() + SandboxedVfsFileType file_type, +#endif // DCHECK_IS_ON() SandboxedVfs* vfs); ~SandboxedVfsFile(); @@ -77,6 +95,10 @@ int sqlite_lock_mode_; // The SandboxedVfs that created this instance. const raw_ptr<SandboxedVfs> vfs_; +#if DCHECK_IS_ON() + // Tracked to check assumptions about SQLite's locking protocol. + const SandboxedVfsFileType file_type_; +#endif // DCHECK_IS_ON() // Used to identify the file in IPCs to the browser process. const base::FilePath file_path_; };
diff --git a/testing/buildbot/chrome.json b/testing/buildbot/chrome.json index a185e3f..3ddf5c5 100644 --- a/testing/buildbot/chrome.json +++ b/testing/buildbot/chrome.json
@@ -1793,7 +1793,7 @@ { "args": [], "cros_board": "atlas", - "cros_img": "atlas-release/R99-14469.8.0", + "cros_img": "atlas-release/R100-14496.0.0", "name": "lacros_all_tast_tests_ATLAS_DEV", "resultdb": { "enable": true, @@ -1823,7 +1823,7 @@ { "args": [], "cros_board": "atlas", - "cros_img": "atlas-release/R97-14324.80.0", + "cros_img": "atlas-release/R98-14388.52.0", "name": "lacros_all_tast_tests_ATLAS_STABLE", "resultdb": { "enable": true, @@ -1853,7 +1853,7 @@ { "args": [], "cros_board": "eve", - "cros_img": "eve-release/R99-14469.8.0", + "cros_img": "eve-release/R100-14496.0.0", "name": "lacros_all_tast_tests_EVE_DEV", "resultdb": { "enable": true, @@ -1883,7 +1883,7 @@ { "args": [], "cros_board": "eve", - "cros_img": "eve-release/R97-14324.80.0", + "cros_img": "eve-release/R98-14388.52.0", "name": "lacros_all_tast_tests_EVE_STABLE", "resultdb": { "enable": true,
diff --git a/testing/buildbot/chromium.android.fyi.json b/testing/buildbot/chromium.android.fyi.json index 96255be..664e1af 100644 --- a/testing/buildbot/chromium.android.fyi.json +++ b/testing/buildbot/chromium.android.fyi.json
@@ -5703,7 +5703,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M99", - "revision": "version:99.0.4844.23" + "revision": "version:99.0.4844.24" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -5967,7 +5967,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M99", - "revision": "version:99.0.4844.23" + "revision": "version:99.0.4844.24" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.android.json b/testing/buildbot/chromium.android.json index e6f476b..b98cfbd 100644 --- a/testing/buildbot/chromium.android.json +++ b/testing/buildbot/chromium.android.json
@@ -43369,7 +43369,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M99", - "revision": "version:99.0.4844.23" + "revision": "version:99.0.4844.24" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -43633,7 +43633,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M99", - "revision": "version:99.0.4844.23" + "revision": "version:99.0.4844.24" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -43972,7 +43972,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M99", - "revision": "version:99.0.4844.23" + "revision": "version:99.0.4844.24" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -44236,7 +44236,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M99", - "revision": "version:99.0.4844.23" + "revision": "version:99.0.4844.24" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -44575,7 +44575,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M99", - "revision": "version:99.0.4844.23" + "revision": "version:99.0.4844.24" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}", @@ -44839,7 +44839,7 @@ { "cipd_package": "chromium/testing/weblayer-x86", "location": "weblayer_instrumentation_test_M99", - "revision": "version:99.0.4844.23" + "revision": "version:99.0.4844.24" }, { "cipd_package": "infra/tools/luci/logdog/butler/${platform}",
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json index cf828daaa..42fb980 100644 --- a/testing/buildbot/chromium.clang.json +++ b/testing/buildbot/chromium.clang.json
@@ -40596,7 +40596,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40608,7 +40608,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "absl_hardening_tests_iPhone 6s 15.0", + "name": "absl_hardening_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40634,8 +40634,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40647,7 +40647,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40659,7 +40659,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone 6s 15.0", + "name": "base_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40685,8 +40685,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40698,7 +40698,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40710,7 +40710,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_crypto_tests_iPhone 6s 15.0", + "name": "boringssl_crypto_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40736,8 +40736,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40749,7 +40749,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40761,7 +40761,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_ssl_tests_iPhone 6s 15.0", + "name": "boringssl_ssl_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40787,8 +40787,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40800,7 +40800,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40812,7 +40812,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone 6s 15.0", + "name": "components_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40838,8 +40838,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40851,7 +40851,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40863,7 +40863,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "crypto_unittests_iPhone 6s 15.0", + "name": "crypto_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40889,8 +40889,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40902,7 +40902,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40914,7 +40914,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone 6s 15.0", + "name": "gfx_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40940,8 +40940,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40953,7 +40953,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -40965,7 +40965,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "google_apis_unittests_iPhone 6s 15.0", + "name": "google_apis_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40991,8 +40991,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41004,7 +41004,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -41016,7 +41016,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone 6s 15.0", + "name": "ios_chrome_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41042,8 +41042,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41055,7 +41055,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -41067,7 +41067,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_net_unittests_iPhone 6s 15.0", + "name": "ios_net_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41093,8 +41093,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41106,7 +41106,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -41118,7 +41118,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone 6s 15.0", + "name": "ios_web_inttests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41144,8 +41144,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41157,7 +41157,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -41169,7 +41169,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone 6s 15.0", + "name": "ios_web_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41195,8 +41195,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41208,7 +41208,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -41220,7 +41220,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone 6s 15.0", + "name": "ios_web_view_inttests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41246,8 +41246,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41259,7 +41259,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -41271,7 +41271,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "net_unittests_iPhone 6s 15.0", + "name": "net_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41297,8 +41297,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41310,7 +41310,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -41322,7 +41322,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone 6s 15.0", + "name": "skia_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41348,8 +41348,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41361,7 +41361,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -41373,7 +41373,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "sql_unittests_iPhone 6s 15.0", + "name": "sql_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41399,8 +41399,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41412,7 +41412,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -41424,7 +41424,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone 6s 15.0", + "name": "ui_base_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41450,8 +41450,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41463,7 +41463,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -41475,7 +41475,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "url_unittests_iPhone 6s 15.0", + "name": "url_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41501,8 +41501,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/testing/buildbot/chromium.fyi.json b/testing/buildbot/chromium.fyi.json index 686e091..5bbe920 100644 --- a/testing/buildbot/chromium.fyi.json +++ b/testing/buildbot/chromium.fyi.json
@@ -21695,6 +21695,31 @@ "gtest_tests": [ { "args": [ + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.browser_tests.filter", + "--", + "--test-launcher-timeout=60000" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "cpu": "arm64", + "inside_docker": "1", + "os": "Ubuntu-20.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 40 + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + }, + { + "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_browsertests.filter", "--", "--disable-gpu", @@ -24313,6 +24338,30 @@ "gtest_tests": [ { "args": [ + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.browser_tests.filter", + "--", + "--test-launcher-timeout=60000" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 40 + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + }, + { + "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_browsertests.filter", "--", "--disable-gpu", @@ -24771,6 +24820,31 @@ "gtest_tests": [ { "args": [ + "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.browser_tests.filter", + "--", + "--test-launcher-timeout=60000", + "--custom-image=workstation.qemu-x64-release" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "swarming": { + "can_use_on_swarming_builders": true, + "dimension_sets": [ + { + "kvm": "1", + "os": "Ubuntu-18.04" + } + ], + "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", + "shards": 40 + }, + "test": "browser_tests", + "test_id_prefix": "ninja://chrome/test:browser_tests/" + }, + { + "args": [ "--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_browsertests.filter", "--", "--disable-gpu", @@ -25248,7 +25322,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25260,7 +25334,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "absl_hardening_tests_iPad Air 2 15.0", + "name": "absl_hardening_tests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25286,8 +25360,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25299,7 +25373,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25311,7 +25385,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "absl_hardening_tests_iPhone X 15.0", + "name": "absl_hardening_tests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25337,8 +25411,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25350,7 +25424,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25362,7 +25436,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPad Air 2 15.0", + "name": "base_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25388,8 +25462,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25401,7 +25475,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25413,7 +25487,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone X 15.0", + "name": "base_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25439,8 +25513,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25452,7 +25526,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25464,7 +25538,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_crypto_tests_iPad Air 2 15.0", + "name": "boringssl_crypto_tests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25490,8 +25564,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25503,7 +25577,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25515,7 +25589,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_crypto_tests_iPhone X 15.0", + "name": "boringssl_crypto_tests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25541,8 +25615,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25554,7 +25628,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25566,7 +25640,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_ssl_tests_iPad Air 2 15.0", + "name": "boringssl_ssl_tests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25592,8 +25666,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25605,7 +25679,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25617,7 +25691,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_ssl_tests_iPhone X 15.0", + "name": "boringssl_ssl_tests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25643,8 +25717,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25656,7 +25730,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25668,7 +25742,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPad Air 2 15.0", + "name": "components_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25694,8 +25768,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25707,7 +25781,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25719,7 +25793,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone X 15.0", + "name": "components_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25745,8 +25819,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25758,7 +25832,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25770,7 +25844,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "crashpad_tests_iPad Air 2 15.0", + "name": "crashpad_tests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25796,8 +25870,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25809,7 +25883,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25821,7 +25895,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "crashpad_tests_iPhone X 15.0", + "name": "crashpad_tests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25847,8 +25921,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25860,7 +25934,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25872,7 +25946,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "crypto_unittests_iPad Air 2 15.0", + "name": "crypto_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25898,8 +25972,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25911,7 +25985,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25923,7 +25997,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "crypto_unittests_iPhone X 15.0", + "name": "crypto_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -25949,8 +26023,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -25962,7 +26036,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -25974,7 +26048,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPad Air 2 15.0", + "name": "gfx_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26000,8 +26074,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26013,7 +26087,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26025,7 +26099,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone X 15.0", + "name": "gfx_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26051,8 +26125,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26064,7 +26138,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26076,7 +26150,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "google_apis_unittests_iPad Air 2 15.0", + "name": "google_apis_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26102,8 +26176,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26115,7 +26189,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26127,7 +26201,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "google_apis_unittests_iPhone X 15.0", + "name": "google_apis_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26153,8 +26227,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26166,7 +26240,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26178,7 +26252,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPad Air 2 15.0", + "name": "ios_chrome_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26204,8 +26278,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26217,7 +26291,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26229,7 +26303,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone X 15.0", + "name": "ios_chrome_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26255,8 +26329,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26268,7 +26342,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26280,7 +26354,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_components_unittests_iPad Air 2 15.0", + "name": "ios_components_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26306,8 +26380,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26319,7 +26393,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26331,7 +26405,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_components_unittests_iPhone X 15.0", + "name": "ios_components_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26357,8 +26431,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26370,7 +26444,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26382,7 +26456,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_net_unittests_iPad Air 2 15.0", + "name": "ios_net_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26408,8 +26482,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26421,7 +26495,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26433,7 +26507,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_net_unittests_iPhone X 15.0", + "name": "ios_net_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26459,8 +26533,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26472,7 +26546,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26484,7 +26558,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_remoting_unittests_iPad Air 2 15.0", + "name": "ios_remoting_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26510,8 +26584,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26523,7 +26597,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26535,7 +26609,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_remoting_unittests_iPhone X 15.0", + "name": "ios_remoting_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26561,8 +26635,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26574,7 +26648,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26586,7 +26660,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_testing_unittests_iPad Air 2 15.0", + "name": "ios_testing_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26612,8 +26686,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26625,7 +26699,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26637,7 +26711,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_testing_unittests_iPhone X 15.0", + "name": "ios_testing_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26663,8 +26737,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26676,7 +26750,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26688,7 +26762,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPad Air 2 15.0", + "name": "ios_web_inttests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26714,8 +26788,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26727,7 +26801,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26739,7 +26813,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone X 15.0", + "name": "ios_web_inttests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26765,8 +26839,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26778,7 +26852,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26790,7 +26864,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPad Air 2 15.0", + "name": "ios_web_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26816,8 +26890,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26829,7 +26903,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26841,7 +26915,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone X 15.0", + "name": "ios_web_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26867,8 +26941,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26880,7 +26954,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26892,7 +26966,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPad Air 2 15.0", + "name": "ios_web_view_inttests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26918,8 +26992,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26931,7 +27005,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26943,7 +27017,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone X 15.0", + "name": "ios_web_view_inttests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -26969,8 +27043,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -26982,7 +27056,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -26994,7 +27068,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPad Air 2 15.0", + "name": "ios_web_view_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27020,8 +27094,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27033,7 +27107,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27045,7 +27119,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone X 15.0", + "name": "ios_web_view_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27071,8 +27145,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27084,7 +27158,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27096,7 +27170,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "net_unittests_iPad Air 2 15.0", + "name": "net_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27122,8 +27196,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27135,7 +27209,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27147,7 +27221,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "net_unittests_iPhone X 15.0", + "name": "net_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27173,8 +27247,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27186,7 +27260,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27198,7 +27272,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "services_unittests_iPad Air 2 15.0", + "name": "services_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27224,8 +27298,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27237,7 +27311,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27249,7 +27323,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "services_unittests_iPhone X 15.0", + "name": "services_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27275,8 +27349,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27288,7 +27362,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27300,7 +27374,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPad Air 2 15.0", + "name": "skia_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27326,8 +27400,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27339,7 +27413,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27351,7 +27425,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone X 15.0", + "name": "skia_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27377,8 +27451,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27390,7 +27464,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27402,7 +27476,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "sql_unittests_iPad Air 2 15.0", + "name": "sql_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27428,8 +27502,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27441,7 +27515,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27453,7 +27527,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "sql_unittests_iPhone X 15.0", + "name": "sql_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27479,8 +27553,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27492,7 +27566,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27504,7 +27578,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPad Air 2 15.0", + "name": "ui_base_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27530,8 +27604,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27543,7 +27617,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27555,7 +27629,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone X 15.0", + "name": "ui_base_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27581,8 +27655,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27594,7 +27668,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27606,7 +27680,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "url_unittests_iPad Air 2 15.0", + "name": "url_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27632,8 +27706,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27645,7 +27719,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27657,7 +27731,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "url_unittests_iPhone X 15.0", + "name": "url_unittests_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27683,8 +27757,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27754,7 +27828,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27766,7 +27840,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "absl_hardening_tests_iPhone 6s 15.0", + "name": "absl_hardening_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27792,8 +27866,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27856,7 +27930,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27868,7 +27942,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPad Air 2 15.0", + "name": "base_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27894,8 +27968,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -27958,7 +28032,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -27970,7 +28044,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone 6s 15.0", + "name": "base_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -27996,8 +28070,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -28060,7 +28134,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -28072,7 +28146,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone 6s Plus 15.0", + "name": "base_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -28098,8 +28172,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -28162,7 +28236,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -28174,7 +28248,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone SE (1st generation) 15.0", + "name": "base_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -28200,8 +28274,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -28264,7 +28338,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -28276,7 +28350,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_crypto_tests_iPhone 6s 15.0", + "name": "boringssl_crypto_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -28302,8 +28376,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -28366,7 +28440,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -28378,7 +28452,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_ssl_tests_iPhone 6s 15.0", + "name": "boringssl_ssl_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -28404,8 +28478,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -28468,7 +28542,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -28480,7 +28554,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPad Air 2 15.0", + "name": "components_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -28506,8 +28580,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -28570,7 +28644,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -28582,7 +28656,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone 6s 15.0", + "name": "components_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -28608,8 +28682,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -28672,7 +28746,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -28684,7 +28758,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone 6s Plus 15.0", + "name": "components_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -28710,8 +28784,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -28774,7 +28848,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -28786,7 +28860,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone SE (1st generation) 15.0", + "name": "components_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -28812,8 +28886,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -28876,7 +28950,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -28888,7 +28962,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "crypto_unittests_iPhone 6s 15.0", + "name": "crypto_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -28914,8 +28988,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -28978,7 +29052,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -28990,7 +29064,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPad Air 2 15.0", + "name": "gfx_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -29016,8 +29090,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -29080,7 +29154,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -29092,7 +29166,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone 6s 15.0", + "name": "gfx_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -29118,8 +29192,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -29182,7 +29256,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -29194,7 +29268,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone 6s Plus 15.0", + "name": "gfx_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -29220,8 +29294,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -29284,7 +29358,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -29296,7 +29370,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone SE (1st generation) 15.0", + "name": "gfx_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -29322,8 +29396,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -29386,7 +29460,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -29398,7 +29472,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "google_apis_unittests_iPhone 6s 15.0", + "name": "google_apis_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -29424,8 +29498,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -29489,7 +29563,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -29502,7 +29576,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -29528,8 +29602,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -29593,7 +29667,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -29606,7 +29680,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -29632,8 +29706,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -29697,7 +29771,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -29710,7 +29784,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -29736,8 +29810,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -29802,7 +29876,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -29815,7 +29889,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -29841,8 +29915,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -29908,7 +29982,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -29921,7 +29995,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 15.0", + "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -29947,8 +30021,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -30014,7 +30088,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -30027,7 +30101,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_integration_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -30053,8 +30127,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -30120,7 +30194,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -30133,7 +30207,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -30159,8 +30233,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -30226,7 +30300,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -30239,7 +30313,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_settings_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -30265,8 +30339,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -30332,7 +30406,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -30345,7 +30419,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_settings_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -30371,8 +30445,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -30437,7 +30511,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -30450,7 +30524,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -30476,8 +30550,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -30541,7 +30615,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -30554,7 +30628,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 15.0", + "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -30580,8 +30654,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -30645,7 +30719,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -30658,7 +30732,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_signin_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -30684,8 +30758,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -30749,7 +30823,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -30762,7 +30836,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -30788,8 +30862,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -30853,7 +30927,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -30866,7 +30940,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -30892,8 +30966,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -30957,7 +31031,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -30970,7 +31044,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_smoke_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -30996,8 +31070,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -31062,7 +31136,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -31075,7 +31149,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -31101,8 +31175,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -31168,7 +31242,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -31181,7 +31255,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 15.0", + "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -31207,8 +31281,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -31274,7 +31348,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -31287,7 +31361,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_ui_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -31313,8 +31387,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -31378,7 +31452,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -31390,7 +31464,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPad Air 2 15.0", + "name": "ios_chrome_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -31416,8 +31490,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -31480,7 +31554,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -31492,7 +31566,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone 6s 15.0", + "name": "ios_chrome_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -31518,8 +31592,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -31582,7 +31656,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -31594,7 +31668,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone 6s Plus 15.0", + "name": "ios_chrome_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -31620,8 +31694,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -31684,7 +31758,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -31696,7 +31770,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone SE (1st generation) 15.0", + "name": "ios_chrome_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -31722,8 +31796,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -31787,7 +31861,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -31800,7 +31874,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_web_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -31826,8 +31900,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -31891,7 +31965,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -31904,7 +31978,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_web_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -31930,8 +32004,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -31995,7 +32069,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -32008,7 +32082,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_web_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -32034,8 +32108,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -32098,7 +32172,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -32110,7 +32184,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_components_unittests_iPhone 6s 15.0", + "name": "ios_components_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -32136,8 +32210,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -32200,7 +32274,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -32212,7 +32286,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_net_unittests_iPhone 6s 15.0", + "name": "ios_net_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -32238,8 +32312,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -32302,7 +32376,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -32314,7 +32388,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_remoting_unittests_iPhone 6s 15.0", + "name": "ios_remoting_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -32340,8 +32414,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -32405,7 +32479,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -32418,7 +32492,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPad Air 2 15.0", + "name": "ios_showcase_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -32444,8 +32518,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -32509,7 +32583,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -32522,7 +32596,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPhone 7 15.0", + "name": "ios_showcase_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -32548,8 +32622,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -32613,7 +32687,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -32626,7 +32700,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPhone X 15.0", + "name": "ios_showcase_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -32652,8 +32726,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -32716,7 +32790,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -32728,7 +32802,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_testing_unittests_iPhone 6s 15.0", + "name": "ios_testing_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -32754,8 +32828,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -32818,7 +32892,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -32830,7 +32904,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPad Air 2 15.0", + "name": "ios_web_inttests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -32856,8 +32930,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -32920,7 +32994,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -32932,7 +33006,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone 6s 15.0", + "name": "ios_web_inttests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -32958,8 +33032,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -33022,7 +33096,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -33034,7 +33108,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone 6s Plus 15.0", + "name": "ios_web_inttests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -33060,8 +33134,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -33124,7 +33198,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -33136,7 +33210,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone SE (1st generation) 15.0", + "name": "ios_web_inttests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -33162,8 +33236,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -33227,7 +33301,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -33240,7 +33314,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPad Air 2 15.0", + "name": "ios_web_shell_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -33266,8 +33340,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -33331,7 +33405,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -33344,7 +33418,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPhone 6s 15.0", + "name": "ios_web_shell_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -33370,8 +33444,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -33435,7 +33509,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -33448,7 +33522,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPhone 7 15.0", + "name": "ios_web_shell_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -33474,8 +33548,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -33538,7 +33612,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -33550,7 +33624,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPad Air 2 15.0", + "name": "ios_web_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -33576,8 +33650,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -33640,7 +33714,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -33652,7 +33726,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone 6s 15.0", + "name": "ios_web_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -33678,8 +33752,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -33742,7 +33816,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -33754,7 +33828,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone 6s Plus 15.0", + "name": "ios_web_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -33780,8 +33854,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -33844,7 +33918,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -33856,7 +33930,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone SE (1st generation) 15.0", + "name": "ios_web_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -33882,8 +33956,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -33946,7 +34020,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -33958,7 +34032,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPad Air 2 15.0", + "name": "ios_web_view_inttests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -33984,8 +34058,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -34048,7 +34122,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34060,7 +34134,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone 6s 15.0", + "name": "ios_web_view_inttests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -34086,8 +34160,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -34150,7 +34224,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34162,7 +34236,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone 6s Plus 15.0", + "name": "ios_web_view_inttests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -34188,8 +34262,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -34252,7 +34326,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34264,7 +34338,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone SE (1st generation) 15.0", + "name": "ios_web_view_inttests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -34290,8 +34364,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -34354,7 +34428,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34366,7 +34440,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPad Air 2 15.0", + "name": "ios_web_view_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -34392,8 +34466,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -34456,7 +34530,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34468,7 +34542,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone 6s 15.0", + "name": "ios_web_view_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -34494,8 +34568,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -34558,7 +34632,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34570,7 +34644,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone 6s Plus 15.0", + "name": "ios_web_view_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -34596,8 +34670,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -34660,7 +34734,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34672,7 +34746,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone SE (1st generation) 15.0", + "name": "ios_web_view_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -34698,8 +34772,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -34762,7 +34836,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34774,7 +34848,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "net_unittests_iPhone 6s 15.0", + "name": "net_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -34800,8 +34874,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -34864,7 +34938,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34876,7 +34950,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "services_unittests_iPhone 6s 15.0", + "name": "services_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -34902,8 +34976,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -34966,7 +35040,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -34978,7 +35052,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPad Air 2 15.0", + "name": "skia_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -35004,8 +35078,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -35068,7 +35142,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35080,7 +35154,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone 6s 15.0", + "name": "skia_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -35106,8 +35180,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -35170,7 +35244,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35182,7 +35256,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone 6s Plus 15.0", + "name": "skia_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -35208,8 +35282,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -35272,7 +35346,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35284,7 +35358,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone SE (1st generation) 15.0", + "name": "skia_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -35310,8 +35384,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -35374,7 +35448,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35386,7 +35460,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "sql_unittests_iPhone 6s 15.0", + "name": "sql_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -35412,8 +35486,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -35476,7 +35550,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35488,7 +35562,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPad Air 2 15.0", + "name": "ui_base_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -35514,8 +35588,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -35578,7 +35652,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35590,7 +35664,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone 6s 15.0", + "name": "ui_base_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -35616,8 +35690,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -35680,7 +35754,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35692,7 +35766,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone 6s Plus 15.0", + "name": "ui_base_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -35718,8 +35792,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -35782,7 +35856,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35794,7 +35868,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone SE (1st generation) 15.0", + "name": "ui_base_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -35820,8 +35894,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -35884,7 +35958,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -35896,7 +35970,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "url_unittests_iPhone 6s 15.0", + "name": "url_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -35922,8 +35996,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -35993,7 +36067,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -36008,7 +36082,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "absl_hardening_tests_iPhone 6s 15.0", + "name": "absl_hardening_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -36034,8 +36108,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -36101,7 +36175,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -36116,7 +36190,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPad Air 2 15.0", + "name": "base_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -36142,8 +36216,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -36209,7 +36283,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -36224,7 +36298,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone 6s 15.0", + "name": "base_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -36250,8 +36324,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -36317,7 +36391,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -36332,7 +36406,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone 6s Plus 15.0", + "name": "base_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -36358,8 +36432,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -36425,7 +36499,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -36440,7 +36514,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone SE (1st generation) 15.0", + "name": "base_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -36466,8 +36540,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -36533,7 +36607,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -36548,7 +36622,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_crypto_tests_iPhone 6s 15.0", + "name": "boringssl_crypto_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -36574,8 +36648,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -36641,7 +36715,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -36656,7 +36730,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_ssl_tests_iPhone 6s 15.0", + "name": "boringssl_ssl_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -36682,8 +36756,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -36749,7 +36823,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -36764,7 +36838,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPad Air 2 15.0", + "name": "components_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -36790,8 +36864,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -36857,7 +36931,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -36872,7 +36946,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone 6s 15.0", + "name": "components_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -36898,8 +36972,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -36965,7 +37039,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -36980,7 +37054,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone 6s Plus 15.0", + "name": "components_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -37006,8 +37080,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -37073,7 +37147,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -37088,7 +37162,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone SE (1st generation) 15.0", + "name": "components_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -37114,8 +37188,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -37181,7 +37255,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -37196,7 +37270,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "crypto_unittests_iPhone 6s 15.0", + "name": "crypto_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -37222,8 +37296,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -37289,7 +37363,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -37304,7 +37378,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPad Air 2 15.0", + "name": "gfx_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -37330,8 +37404,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -37397,7 +37471,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -37412,7 +37486,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone 6s 15.0", + "name": "gfx_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -37438,8 +37512,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -37505,7 +37579,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -37520,7 +37594,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone 6s Plus 15.0", + "name": "gfx_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -37546,8 +37620,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -37613,7 +37687,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -37628,7 +37702,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone SE (1st generation) 15.0", + "name": "gfx_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -37654,8 +37728,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -37721,7 +37795,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -37736,7 +37810,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "google_apis_unittests_iPhone 6s 15.0", + "name": "google_apis_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -37762,8 +37836,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -37830,7 +37904,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -37846,7 +37920,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -37872,8 +37946,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -37940,7 +38014,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -37956,7 +38030,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -37982,8 +38056,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -38050,7 +38124,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -38066,7 +38140,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -38092,8 +38166,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -38161,7 +38235,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -38177,7 +38251,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -38203,8 +38277,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -38273,7 +38347,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -38289,7 +38363,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 15.0", + "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -38315,8 +38389,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -38385,7 +38459,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -38401,7 +38475,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_integration_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -38427,8 +38501,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -38497,7 +38571,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -38513,7 +38587,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -38539,8 +38613,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -38609,7 +38683,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -38625,7 +38699,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_settings_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -38651,8 +38725,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -38721,7 +38795,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -38737,7 +38811,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_settings_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -38763,8 +38837,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -38832,7 +38906,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -38848,7 +38922,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -38874,8 +38948,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -38942,7 +39016,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -38958,7 +39032,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 15.0", + "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -38984,8 +39058,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -39052,7 +39126,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -39068,7 +39142,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_signin_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -39094,8 +39168,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -39162,7 +39236,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -39178,7 +39252,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -39204,8 +39278,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -39272,7 +39346,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -39288,7 +39362,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -39314,8 +39388,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -39382,7 +39456,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -39398,7 +39472,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_smoke_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -39424,8 +39498,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -39493,7 +39567,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -39509,7 +39583,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -39535,8 +39609,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -39605,7 +39679,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -39621,7 +39695,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 15.0", + "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -39647,8 +39721,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -39717,7 +39791,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -39733,7 +39807,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_ui_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -39759,8 +39833,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -39827,7 +39901,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -39842,7 +39916,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPad Air 2 15.0", + "name": "ios_chrome_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -39868,8 +39942,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -39935,7 +40009,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -39950,7 +40024,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone 6s 15.0", + "name": "ios_chrome_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -39976,8 +40050,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40043,7 +40117,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -40058,7 +40132,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone 6s Plus 15.0", + "name": "ios_chrome_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40084,8 +40158,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40151,7 +40225,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -40166,7 +40240,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone SE (1st generation) 15.0", + "name": "ios_chrome_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40192,8 +40266,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40260,7 +40334,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -40276,7 +40350,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_web_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40302,8 +40376,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40370,7 +40444,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -40386,7 +40460,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_web_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40412,8 +40486,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40480,7 +40554,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -40496,7 +40570,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_web_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40522,8 +40596,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40589,7 +40663,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -40604,7 +40678,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_components_unittests_iPhone 6s 15.0", + "name": "ios_components_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40630,8 +40704,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40697,7 +40771,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -40712,7 +40786,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_net_unittests_iPhone 6s 15.0", + "name": "ios_net_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40738,8 +40812,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40805,7 +40879,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -40820,7 +40894,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_remoting_unittests_iPhone 6s 15.0", + "name": "ios_remoting_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40846,8 +40920,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -40914,7 +40988,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -40930,7 +41004,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPad Air 2 15.0", + "name": "ios_showcase_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -40956,8 +41030,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41024,7 +41098,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -41040,7 +41114,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPhone 7 15.0", + "name": "ios_showcase_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41066,8 +41140,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41134,7 +41208,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -41150,7 +41224,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPhone X 15.0", + "name": "ios_showcase_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41176,8 +41250,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41243,7 +41317,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -41258,7 +41332,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_testing_unittests_iPhone 6s 15.0", + "name": "ios_testing_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41284,8 +41358,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41351,7 +41425,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -41366,7 +41440,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPad Air 2 15.0", + "name": "ios_web_inttests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41392,8 +41466,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41459,7 +41533,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -41474,7 +41548,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone 6s 15.0", + "name": "ios_web_inttests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41500,8 +41574,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41567,7 +41641,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -41582,7 +41656,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone 6s Plus 15.0", + "name": "ios_web_inttests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41608,8 +41682,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41675,7 +41749,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -41690,7 +41764,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone SE (1st generation) 15.0", + "name": "ios_web_inttests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41716,8 +41790,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41784,7 +41858,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -41800,7 +41874,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPad Air 2 15.0", + "name": "ios_web_shell_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41826,8 +41900,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -41894,7 +41968,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -41910,7 +41984,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPhone 6s 15.0", + "name": "ios_web_shell_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -41936,8 +42010,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -42004,7 +42078,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -42020,7 +42094,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPhone 7 15.0", + "name": "ios_web_shell_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -42046,8 +42120,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -42113,7 +42187,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -42128,7 +42202,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPad Air 2 15.0", + "name": "ios_web_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -42154,8 +42228,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -42221,7 +42295,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -42236,7 +42310,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone 6s 15.0", + "name": "ios_web_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -42262,8 +42336,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -42329,7 +42403,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -42344,7 +42418,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone 6s Plus 15.0", + "name": "ios_web_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -42370,8 +42444,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -42437,7 +42511,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -42452,7 +42526,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone SE (1st generation) 15.0", + "name": "ios_web_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -42478,8 +42552,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -42545,7 +42619,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -42560,7 +42634,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPad Air 2 15.0", + "name": "ios_web_view_inttests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -42586,8 +42660,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -42653,7 +42727,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -42668,7 +42742,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone 6s 15.0", + "name": "ios_web_view_inttests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -42694,8 +42768,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -42761,7 +42835,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -42776,7 +42850,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone 6s Plus 15.0", + "name": "ios_web_view_inttests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -42802,8 +42876,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -42869,7 +42943,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -42884,7 +42958,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone SE (1st generation) 15.0", + "name": "ios_web_view_inttests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -42910,8 +42984,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -42977,7 +43051,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -42992,7 +43066,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPad Air 2 15.0", + "name": "ios_web_view_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -43018,8 +43092,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -43085,7 +43159,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -43100,7 +43174,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone 6s 15.0", + "name": "ios_web_view_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -43126,8 +43200,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -43193,7 +43267,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -43208,7 +43282,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone 6s Plus 15.0", + "name": "ios_web_view_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -43234,8 +43308,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -43301,7 +43375,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -43316,7 +43390,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone SE (1st generation) 15.0", + "name": "ios_web_view_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -43342,8 +43416,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -43409,7 +43483,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -43424,7 +43498,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "net_unittests_iPhone 6s 15.0", + "name": "net_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -43450,8 +43524,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -43517,7 +43591,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -43532,7 +43606,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "services_unittests_iPhone 6s 15.0", + "name": "services_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -43558,8 +43632,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -43625,7 +43699,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -43640,7 +43714,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPad Air 2 15.0", + "name": "skia_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -43666,8 +43740,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -43733,7 +43807,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -43748,7 +43822,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone 6s 15.0", + "name": "skia_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -43774,8 +43848,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -43841,7 +43915,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -43856,7 +43930,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone 6s Plus 15.0", + "name": "skia_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -43882,8 +43956,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -43949,7 +44023,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -43964,7 +44038,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone SE (1st generation) 15.0", + "name": "skia_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -43990,8 +44064,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44057,7 +44131,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -44072,7 +44146,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "sql_unittests_iPhone 6s 15.0", + "name": "sql_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44098,8 +44172,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44165,7 +44239,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -44180,7 +44254,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPad Air 2 15.0", + "name": "ui_base_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44206,8 +44280,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44273,7 +44347,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -44288,7 +44362,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone 6s 15.0", + "name": "ui_base_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44314,8 +44388,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44381,7 +44455,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -44396,7 +44470,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone 6s Plus 15.0", + "name": "ui_base_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44422,8 +44496,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44489,7 +44563,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -44504,7 +44578,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone SE (1st generation) 15.0", + "name": "ui_base_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44530,8 +44604,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44597,7 +44671,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--args-json", "{\"test_args\": [\"--write-compiled-tests-json-to-writable-path\"]}", "--out-dir", @@ -44612,7 +44686,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "url_unittests_iPhone 6s 15.0", + "name": "url_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44638,8 +44712,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44655,7 +44729,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -44667,7 +44741,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "cronet_test_iPhone X 15.0", + "name": "cronet_test_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44693,8 +44767,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44710,7 +44784,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -44722,7 +44796,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "absl_hardening_tests_iPad Air 2 15.0", + "name": "absl_hardening_tests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44748,8 +44822,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44761,7 +44835,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -44773,7 +44847,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPad Air 2 15.0", + "name": "base_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44799,8 +44873,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44812,7 +44886,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -44824,7 +44898,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_crypto_tests_iPad Air 2 15.0", + "name": "boringssl_crypto_tests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44850,8 +44924,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44863,7 +44937,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -44875,7 +44949,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_ssl_tests_iPad Air 2 15.0", + "name": "boringssl_ssl_tests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44901,8 +44975,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44914,7 +44988,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -44926,7 +45000,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPad Air 2 15.0", + "name": "components_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -44952,8 +45026,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -44965,7 +45039,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -44977,7 +45051,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "crypto_unittests_iPad Air 2 15.0", + "name": "crypto_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45003,8 +45077,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45016,7 +45090,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45028,7 +45102,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPad Air 2 15.0", + "name": "gfx_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45054,8 +45128,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45067,7 +45141,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45079,7 +45153,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "google_apis_unittests_iPad Air 2 15.0", + "name": "google_apis_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45105,8 +45179,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45118,7 +45192,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45131,7 +45205,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45157,8 +45231,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45170,7 +45244,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45183,7 +45257,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45209,8 +45283,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -45223,7 +45297,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45236,7 +45310,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45262,8 +45336,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -45276,7 +45350,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45289,7 +45363,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45315,8 +45389,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45328,7 +45402,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45341,7 +45415,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45367,8 +45441,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45380,7 +45454,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45393,7 +45467,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45419,8 +45493,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -45433,7 +45507,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45445,7 +45519,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPad Air 2 15.0", + "name": "ios_chrome_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45471,8 +45545,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45484,7 +45558,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45497,7 +45571,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_web_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45523,8 +45597,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45536,7 +45610,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45548,7 +45622,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_components_unittests_iPad Air 2 15.0", + "name": "ios_components_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45574,8 +45648,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45587,7 +45661,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45599,7 +45673,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_net_unittests_iPad Air 2 15.0", + "name": "ios_net_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45625,8 +45699,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45638,7 +45712,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45650,7 +45724,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_remoting_unittests_iPad Air 2 15.0", + "name": "ios_remoting_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45676,8 +45750,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45689,7 +45763,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45702,7 +45776,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPad Air 2 15.0", + "name": "ios_showcase_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45728,8 +45802,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45741,7 +45815,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45753,7 +45827,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_testing_unittests_iPad Air 2 15.0", + "name": "ios_testing_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45779,8 +45853,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45792,7 +45866,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45804,7 +45878,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPad Air 2 15.0", + "name": "ios_web_inttests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45830,8 +45904,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45843,7 +45917,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45856,7 +45930,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPad Air 2 15.0", + "name": "ios_web_shell_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45882,8 +45956,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45895,7 +45969,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45907,7 +45981,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPad Air 2 15.0", + "name": "ios_web_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45933,8 +46007,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45946,7 +46020,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -45958,7 +46032,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPad Air 2 15.0", + "name": "ios_web_view_inttests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -45984,8 +46058,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -45997,7 +46071,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -46009,7 +46083,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPad Air 2 15.0", + "name": "ios_web_view_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -46035,8 +46109,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -46048,7 +46122,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -46060,7 +46134,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "net_unittests_iPad Air 2 15.0", + "name": "net_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -46086,8 +46160,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -46099,7 +46173,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -46111,7 +46185,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "services_unittests_iPad Air 2 15.0", + "name": "services_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -46137,8 +46211,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -46150,7 +46224,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -46162,7 +46236,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPad Air 2 15.0", + "name": "skia_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -46188,8 +46262,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -46201,7 +46275,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -46213,7 +46287,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "sql_unittests_iPad Air 2 15.0", + "name": "sql_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -46239,8 +46313,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -46252,7 +46326,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -46264,7 +46338,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPad Air 2 15.0", + "name": "ui_base_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -46290,8 +46364,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -46303,7 +46377,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -46315,7 +46389,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "url_unittests_iPad Air 2 15.0", + "name": "url_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -46341,8 +46415,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/testing/buildbot/chromium.mac.json b/testing/buildbot/chromium.mac.json index 2418d0a..f985fe4 100644 --- a/testing/buildbot/chromium.mac.json +++ b/testing/buildbot/chromium.mac.json
@@ -12204,7 +12204,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -12217,7 +12217,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "absl_hardening_tests_iPhone 6s 15.0", + "name": "absl_hardening_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -12243,8 +12243,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -12308,7 +12308,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -12321,7 +12321,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPad Air 2 15.0", + "name": "base_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -12347,8 +12347,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -12412,7 +12412,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -12425,7 +12425,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone 6s 15.0", + "name": "base_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -12451,8 +12451,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -12516,7 +12516,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -12529,7 +12529,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone 6s Plus 15.0", + "name": "base_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -12555,8 +12555,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -12620,7 +12620,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -12633,7 +12633,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "base_unittests_iPhone SE (1st generation) 15.0", + "name": "base_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -12659,8 +12659,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -12724,7 +12724,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -12737,7 +12737,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_crypto_tests_iPhone 6s 15.0", + "name": "boringssl_crypto_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -12763,8 +12763,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -12828,7 +12828,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -12841,7 +12841,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "boringssl_ssl_tests_iPhone 6s 15.0", + "name": "boringssl_ssl_tests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -12867,8 +12867,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -12932,7 +12932,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -12945,7 +12945,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPad Air 2 15.0", + "name": "components_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -12971,8 +12971,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -13036,7 +13036,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -13049,7 +13049,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone 6s 15.0", + "name": "components_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -13075,8 +13075,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -13140,7 +13140,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -13153,7 +13153,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone 6s Plus 15.0", + "name": "components_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -13179,8 +13179,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -13244,7 +13244,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -13257,7 +13257,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "components_unittests_iPhone SE (1st generation) 15.0", + "name": "components_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -13283,8 +13283,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -13348,7 +13348,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -13361,7 +13361,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "crypto_unittests_iPhone 6s 15.0", + "name": "crypto_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -13387,8 +13387,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -13452,7 +13452,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -13465,7 +13465,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPad Air 2 15.0", + "name": "gfx_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -13491,8 +13491,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -13556,7 +13556,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -13569,7 +13569,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone 6s 15.0", + "name": "gfx_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -13595,8 +13595,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -13660,7 +13660,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -13673,7 +13673,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone 6s Plus 15.0", + "name": "gfx_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -13699,8 +13699,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -13764,7 +13764,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -13777,7 +13777,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "gfx_unittests_iPhone SE (1st generation) 15.0", + "name": "gfx_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -13803,8 +13803,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -13868,7 +13868,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -13881,7 +13881,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "google_apis_unittests_iPhone 6s 15.0", + "name": "google_apis_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -13907,8 +13907,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -13974,7 +13974,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -13988,7 +13988,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 15.0", + "name": "ios_chrome_integration_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -14014,8 +14014,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -14081,7 +14081,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -14095,7 +14095,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 15.0", + "name": "ios_chrome_signin_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -14121,8 +14121,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -14188,7 +14188,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -14202,7 +14202,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 15.0", + "name": "ios_chrome_ui_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -14228,8 +14228,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -14294,7 +14294,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -14307,7 +14307,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPad Air 2 15.0", + "name": "ios_chrome_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -14333,8 +14333,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -14398,7 +14398,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -14411,7 +14411,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone 6s 15.0", + "name": "ios_chrome_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -14437,8 +14437,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -14502,7 +14502,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -14515,7 +14515,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone 6s Plus 15.0", + "name": "ios_chrome_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -14541,8 +14541,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -14606,7 +14606,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -14619,7 +14619,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_unittests_iPhone SE (1st generation) 15.0", + "name": "ios_chrome_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -14645,8 +14645,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -14710,7 +14710,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -14723,7 +14723,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_components_unittests_iPhone 6s 15.0", + "name": "ios_components_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -14749,8 +14749,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -14814,7 +14814,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -14827,7 +14827,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_net_unittests_iPhone 6s 15.0", + "name": "ios_net_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -14853,8 +14853,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -14918,7 +14918,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -14931,7 +14931,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_remoting_unittests_iPhone 6s 15.0", + "name": "ios_remoting_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -14957,8 +14957,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -15022,7 +15022,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -15035,7 +15035,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_testing_unittests_iPhone 6s 15.0", + "name": "ios_testing_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -15061,8 +15061,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -15126,7 +15126,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -15139,7 +15139,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPad Air 2 15.0", + "name": "ios_web_inttests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -15165,8 +15165,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -15230,7 +15230,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -15243,7 +15243,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone 6s 15.0", + "name": "ios_web_inttests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -15269,8 +15269,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -15334,7 +15334,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -15347,7 +15347,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone 6s Plus 15.0", + "name": "ios_web_inttests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -15373,8 +15373,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -15438,7 +15438,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -15451,7 +15451,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_inttests_iPhone SE (1st generation) 15.0", + "name": "ios_web_inttests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -15477,8 +15477,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -15543,7 +15543,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -15557,7 +15557,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPhone 6s 15.0", + "name": "ios_web_shell_eg2tests_module_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -15583,8 +15583,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -15648,7 +15648,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -15661,7 +15661,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPad Air 2 15.0", + "name": "ios_web_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -15687,8 +15687,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -15752,7 +15752,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -15765,7 +15765,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone 6s 15.0", + "name": "ios_web_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -15791,8 +15791,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -15856,7 +15856,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -15869,7 +15869,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone 6s Plus 15.0", + "name": "ios_web_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -15895,8 +15895,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -15960,7 +15960,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -15973,7 +15973,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_unittests_iPhone SE (1st generation) 15.0", + "name": "ios_web_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -15999,8 +15999,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -16064,7 +16064,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -16077,7 +16077,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPad Air 2 15.0", + "name": "ios_web_view_inttests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -16103,8 +16103,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -16168,7 +16168,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -16181,7 +16181,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone 6s 15.0", + "name": "ios_web_view_inttests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -16207,8 +16207,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -16272,7 +16272,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -16285,7 +16285,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone 6s Plus 15.0", + "name": "ios_web_view_inttests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -16311,8 +16311,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -16376,7 +16376,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -16389,7 +16389,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_inttests_iPhone SE (1st generation) 15.0", + "name": "ios_web_view_inttests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -16415,8 +16415,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -16480,7 +16480,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -16493,7 +16493,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPad Air 2 15.0", + "name": "ios_web_view_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -16519,8 +16519,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -16584,7 +16584,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -16597,7 +16597,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone 6s 15.0", + "name": "ios_web_view_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -16623,8 +16623,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -16688,7 +16688,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -16701,7 +16701,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone 6s Plus 15.0", + "name": "ios_web_view_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -16727,8 +16727,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -16792,7 +16792,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -16805,7 +16805,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_view_unittests_iPhone SE (1st generation) 15.0", + "name": "ios_web_view_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -16831,8 +16831,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -16896,7 +16896,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -16909,7 +16909,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "net_unittests_iPhone 6s 15.0", + "name": "net_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -16935,8 +16935,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -17000,7 +17000,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -17013,7 +17013,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "services_unittests_iPhone 6s 15.0", + "name": "services_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -17039,8 +17039,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -17104,7 +17104,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -17117,7 +17117,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPad Air 2 15.0", + "name": "skia_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -17143,8 +17143,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -17208,7 +17208,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -17221,7 +17221,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone 6s 15.0", + "name": "skia_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -17247,8 +17247,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -17312,7 +17312,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -17325,7 +17325,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone 6s Plus 15.0", + "name": "skia_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -17351,8 +17351,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -17416,7 +17416,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -17429,7 +17429,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "skia_unittests_iPhone SE (1st generation) 15.0", + "name": "skia_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -17455,8 +17455,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -17520,7 +17520,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -17533,7 +17533,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "sql_unittests_iPhone 6s 15.0", + "name": "sql_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -17559,8 +17559,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -17624,7 +17624,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -17637,7 +17637,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPad Air 2 15.0", + "name": "ui_base_unittests_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -17663,8 +17663,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -17728,7 +17728,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -17741,7 +17741,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone 6s 15.0", + "name": "ui_base_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -17767,8 +17767,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -17832,7 +17832,7 @@ "--platform", "iPhone 6s Plus", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -17845,7 +17845,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone 6s Plus 15.0", + "name": "ui_base_unittests_iPhone 6s Plus 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -17871,8 +17871,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -17936,7 +17936,7 @@ "--platform", "iPhone SE (1st generation)", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -17949,7 +17949,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ui_base_unittests_iPhone SE (1st generation) 15.0", + "name": "ui_base_unittests_iPhone SE (1st generation) 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -17975,8 +17975,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -18040,7 +18040,7 @@ "--platform", "iPhone 6s", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -18053,7 +18053,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "url_unittests_iPhone 6s 15.0", + "name": "url_unittests_iPhone 6s 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -18079,8 +18079,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -18152,7 +18152,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -18166,7 +18166,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_bookmarks_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -18192,8 +18192,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -18258,7 +18258,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -18272,7 +18272,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_bookmarks_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -18298,8 +18298,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -18364,7 +18364,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -18378,7 +18378,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_bookmarks_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -18404,8 +18404,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -18471,7 +18471,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -18485,7 +18485,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_integration_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -18511,8 +18511,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -18579,7 +18579,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -18593,7 +18593,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_integration_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_integration_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -18619,8 +18619,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -18687,7 +18687,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -18701,7 +18701,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_settings_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -18727,8 +18727,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -18795,7 +18795,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -18809,7 +18809,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_settings_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -18835,8 +18835,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -18903,7 +18903,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -18917,7 +18917,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_settings_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_settings_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -18943,8 +18943,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -19010,7 +19010,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -19024,7 +19024,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_signin_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -19050,8 +19050,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -19116,7 +19116,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -19130,7 +19130,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_signin_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_signin_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -19156,8 +19156,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -19222,7 +19222,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -19236,7 +19236,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_smoke_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -19262,8 +19262,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -19328,7 +19328,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -19342,7 +19342,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_smoke_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -19368,8 +19368,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -19434,7 +19434,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -19448,7 +19448,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_smoke_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_smoke_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -19474,8 +19474,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -19541,7 +19541,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -19555,7 +19555,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_ui_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -19581,8 +19581,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -19649,7 +19649,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -19663,7 +19663,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_ui_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_ui_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -19689,8 +19689,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com", @@ -19756,7 +19756,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -19770,7 +19770,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPad Air 2 15.0", + "name": "ios_chrome_web_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -19796,8 +19796,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -19862,7 +19862,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -19876,7 +19876,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPhone 7 15.0", + "name": "ios_chrome_web_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -19902,8 +19902,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -19968,7 +19968,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -19982,7 +19982,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_chrome_web_eg2tests_module_iPhone X 15.0", + "name": "ios_chrome_web_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -20008,8 +20008,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -20074,7 +20074,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -20088,7 +20088,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPad Air 2 15.0", + "name": "ios_showcase_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -20114,8 +20114,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -20180,7 +20180,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -20194,7 +20194,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPhone 7 15.0", + "name": "ios_showcase_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -20220,8 +20220,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -20286,7 +20286,7 @@ "--platform", "iPhone X", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -20300,7 +20300,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_showcase_eg2tests_module_iPhone X 15.0", + "name": "ios_showcase_eg2tests_module_iPhone X 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -20326,8 +20326,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -20392,7 +20392,7 @@ "--platform", "iPad Air 2", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -20406,7 +20406,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPad Air 2 15.0", + "name": "ios_web_shell_eg2tests_module_iPad Air 2 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -20432,8 +20432,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -20498,7 +20498,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -20512,7 +20512,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_web_shell_eg2tests_module_iPhone 7 15.0", + "name": "ios_web_shell_eg2tests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -20538,8 +20538,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com" @@ -21757,7 +21757,7 @@ "--platform", "iPhone 7", "--version", - "15.0", + "15.2", "--out-dir", "${ISOLATED_OUTDIR}", "--xcode-build-version", @@ -21770,7 +21770,7 @@ "args": [], "script": "//testing/merge_scripts/standard_isolated_script_merge.py" }, - "name": "ios_crash_xcuitests_module_iPhone 7 15.0", + "name": "ios_crash_xcuitests_module_iPhone 7 15.2", "resultdb": { "enable": true, "has_native_resultdb_integration": true @@ -21796,8 +21796,8 @@ "path": "Xcode.app" }, { - "name": "runtime_ios_15_0", - "path": "Runtime-ios-15.0" + "name": "runtime_ios_15_2", + "path": "Runtime-ios-15.2" } ], "service_account": "chromium-tester@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/testing/buildbot/filters/BUILD.gn b/testing/buildbot/filters/BUILD.gn index 8f63bc1..da6d10a6 100644 --- a/testing/buildbot/filters/BUILD.gn +++ b/testing/buildbot/filters/BUILD.gn
@@ -66,6 +66,7 @@ "//testing/buildbot/filters/chromeos.msan.browser_tests.oobe_negative.filter", "//testing/buildbot/filters/chromeos.msan.browser_tests.oobe_positive.filter", "//testing/buildbot/filters/code_coverage.browser_tests.filter", + "//testing/buildbot/filters/fuchsia.browser_tests.filter", "//testing/buildbot/filters/linux-chromeos.browser_tests.require_lacros.filter", "//testing/buildbot/filters/linux-lacros.browser_tests.filter", "//testing/buildbot/filters/mac.mac11-arm64-rel.browser_tests.filter",
diff --git a/testing/buildbot/filters/fuchsia.browser_tests.filter b/testing/buildbot/filters/fuchsia.browser_tests.filter new file mode 100644 index 0000000..ab9fecf --- /dev/null +++ b/testing/buildbot/filters/fuchsia.browser_tests.filter
@@ -0,0 +1,1192 @@ +-AbortPaymentHandlerTest.JitPaymentHandlerCanRefuseAbort +-AccessContextAuditBrowserTest.CheckSessionOnly +-AccessContextAuditBrowserTest.MultipleAccesses +-AccessContextAuditBrowserTest.Remove* +-AccessContextAuditBrowserTest.TabClosed +-AccessContextAuditSessionRestoreBrowserTest.RestoreSession +-AccuracyTipBubbleViewBrowserTest.SurveyShownAfterShowingTip +-AccuracyTipBubbleViewDialogBrowserTest.Invoke* +-ActivityLogApiTest.TriggerEvent +-AdsPageLoadMetricsObserverBrowserTest.AggregateCpuTriggersCpuUpdateOverSubframeNavigate +-AdsPageLoadMetricsObserverBrowserTest.FrameRAFTriggersCpuUpdate +-AdsPageLoadMetricsObserverBrowserTest.SubframeNavigate_CpuTimesCumulative +-All/BrowsingDataRemoverBrowserTestP.Web* +-All/CastV2PerformanceTest.Performance* +-All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.Download* +-All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.Keeps* +-All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.PrefChange/0 +-All/ChromeBrowsingDataLifetimeManagerScheduledRemovalTest.Site* +-All/ChromeMultiProfileStartupBrowserTestBase.Post* +-All/CookieSettingsTest.Basic* +-All/CryptotokenBrowserTest.Sign* +-All/DeclarativeNetRequestAllowAllRequestsBrowserTest.Test* +-All/DeclarativeNetRequestBackForwardCacheBrowserTest.Back* +-All/DeclarativeNetRequestBrowserTest.ActionCountPreferenceMultipleWindows/0 +-All/DeclarativeNetRequestBrowserTest.Actions* +-All/DeclarativeNetRequestBrowserTest.Allow* +-All/DeclarativeNetRequestBrowserTest.Block* +-All/DeclarativeNetRequestBrowserTest.ChromeURLS/0 +-All/DeclarativeNetRequestBrowserTest.DynamicRules/0 +-All/DeclarativeNetRequestBrowserTest.Enable_Disable_Reload_Uninstall/0 +-All/DeclarativeNetRequestBrowserTest.FledgeAuctionScripts/0 +-All/DeclarativeNetRequestBrowserTest.Get* +-All/DeclarativeNetRequestBrowserTest.HostAccessPermission/0 +-All/DeclarativeNetRequestBrowserTest.ImageCollapsed/0 +-All/DeclarativeNetRequestBrowserTest.InterceptExtensionScheme/0 +-All/DeclarativeNetRequestBrowserTest.ModifyHeadersBadgeText/0 +-All/DeclarativeNetRequestBrowserTest.MultipleRulesets/0 +-All/DeclarativeNetRequestBrowserTest.OnRuleMatchedDebugAvailability/0 +-All/DeclarativeNetRequestBrowserTest.Pac* +-All/DeclarativeNetRequestBrowserTest.Redirect* +-All/DeclarativeNetRequestBrowserTest.RendererCacheCleared/0 +-All/DeclarativeNetRequestBrowserTest.RulesetPrefsDeletedOnUninstall/0 +-All/DeclarativeNetRequestBrowserTest.TabIdFiltering/0 +-All/DeclarativeNetRequestBrowserTest.UpgradeRules/0 +-All/DeclarativeNetRequestBrowserTest.WarningOnFailedRulesetLoad/0 +-All/DeclarativeNetRequestBrowserTest.WebRequestPriority/0 +-All/DeclarativeNetRequestBrowserTest.WithheldPermissions_Block/0 +-All/DeclarativeNetRequestBrowserTest.ZeroRulesets/0 +-All/DeclarativeNetRequestBrowserTest_Packed.BrowserRestart/0 +-All/DeclarativeNetRequestBrowserTest_Packed.CorruptedIndexedRuleset/0 +-All/DeclarativeNetRequestBrowserTest_Packed.Extension* +-All/DeclarativeNetRequestBrowserTest_Packed.UpdateRespectsPermission/0 +-All/DeclarativeNetRequestGlobalRulesBrowserTest_Packed.GlobalRulesBrowserRestart/0 +-All/DeclarativeNetRequestGlobalRulesBrowserTest_Packed.PackedUpdateAndReload/0 +-All/DeclarativeNetRequestGlobalRulesBrowserTest_Packed.UpdateEnabledRulesetsAfterPackedUpdate/0 +-All/DeclarativeNetRequestHostPermissionsBrowserTest.NoPermissions/0 +-All/DeclarativeNetRequestHostPermissionsBrowserTest.SubframesRequireNoInitiatorPermissions/0 +-All/DeclarativeNetRequestIdentifiabilityTest.DeclarativeBlockRecorded/0 +-All/DeclarativeNetRequestResourceTypeBrowserTest.Test* +-All/DeclarativeNetRequestSubresourceWebBundlesBrowserTest.Request* +-All/DeclarativeNetRequestSubresourceWebBundlesBrowserTest.WebBundleRequestRedirected/0 +-All/DeclarativeNetRequestWebTransportTest.BlockRequests/0 +-All/DownloadFramePolicyBrowserTest_UpdateIframeSandboxFlags.Effective* +-All/DownloadFramePolicyBrowserTest_UpdateIframeSandboxFlags.Pending* +-All/DownloadReferrerPolicyTest.Alt* +-All/DownloadReferrerPolicyTest.Download* +-All/DownloadReferrerPolicyTest.Save* +-All/DownloadTestWithOptionalSafetyTipsFeature.Safety* +-All/ExtensionCrxInstallerTestWithWithholdingUI.WithholdingHostsOnInstall/0 +-All/ExtensionURLLoaderThrottleWithSplitCacheBrowserTest.Do* +-All/HostedAppIsolatedOriginTest.AppBroaderThanIsolatedOrigin/0 +-All/HostedAppIsolatedOriginTest.NestedIsolatedOriginStaysOutsideApp/0 +-All/HostedAppJitTestBaseDefaultDisabled.JITDisabledTest/0 +-All/HostedAppJitTestBaseDefaultEnabled.JITDisabledTest/0 +-All/HostedAppOriginIsolationTest.Isolated* +-All/HostedAppProcessModelTest.AppRegistrarExcludesPackaged/0 +-All/HostedAppProcessModelTest.BackgroundPageWithAppCoveringDifferentSites/0 +-All/HostedAppProcessModelTest.FromOutsideHostedApp/0 +-All/HostedAppProcessModelTest.IframeNavigationsInsideHostedApp/0 +-All/HostedAppProcessModelTest.IframesInsideHostedApp/0 +-All/HostedAppProcessModelTest.NavigateToAppURLWithDoubleSlashPath/0 +-All/HostedAppProcessModelTest.PopupsInsideHostedApp/0 +-All/HostedAppSitePerProcessTest.CrossSiteNavigationsWithinApp/0 +-All/HostedAppSitePerProcessTest.Do* +-All/HostedAppTest.HasReloadButton/0 +-All/HostedAppTest.NotWebApp/0 +-All/HostedAppTestWithAutoupgradesDisabled.MixedContentInPlatformApp/0 +-All/HostedAppTestWithAutoupgradesDisabled.Should* +-All/HostedOrWebAppTest.CanUserUninstall/HostedApp +-All/HostedOrWebAppTest.Ctrl* +-All/HostedOrWebAppTest.Should* +-All/HostedOrWebAppTest.SubframeRedirectsToHostedApp/HostedApp +-All/HostedOrWebAppTest.Web* +-All/LoadingPredictorNetworkIsolationKeyBrowserTest.Loading* +-All/LoginPromptBrowserTest.Block* +-All/LoginPromptBrowserTest.Should* +-All/LookalikeUrlNavigationThrottleDigitalAssetLinksBrowserTest.Valid* +-All/ManifestUpdateManagerBrowserTest_AppIdentityParameterized.Check* +-All/ManifestUpdateManagerBrowserTest_UpdateDialog.Check* +-All/ManifestUpdateManagerBrowserTest_UpdateDialog.ScopeChangeWithProductIconChange/UpdateDialogEnabled +-All/ManifestUpdateManagerBrowserTest_UpdateDialog.Shortcut* +-All/MediaEngagementAutoplayBrowserTest.Preloaded* +-All/MediaEngagementAutoplayBrowserTest.Use* +-All/MediaHistoryBrowserTest.Do* +-All/MediaHistoryBrowserTest.Record* +-All/NetworkRequestMetricsBrowserTest.Download* +-All/NoStatePrefetchBrowserTestHttpCache_DefaultAndDoubleKeyedHttpCache.Load* +-All/OneTimePermissionPromptBubbleViewBrowserTest.Invoke* +-All/OtherFrameNavigationDownloadBrowserTest_AdFrame.Download* +-All/PaymentHandlerJustInTimeInstallationTestWithParam.MultiplePaymentMethods/0 +-All/PermissionPromptBubbleViewBrowserTest.Active* +-All/PermissionPromptBubbleViewBrowserTest.Invoke* +-All/PopupBrowserTest.Move* +-All/ProfileNetworkContextServiceDiskCacheBrowsertest.DiskCacheLocation/1 +-All/RendererEventInjectionTest.TestRootTransform/0 +-All/ReportingBrowserTest.Crash* +-All/SafetyTipPageInfoBubbleViewDigitalAssetLinksBrowserTest.NoShowOnDigitalAssetLinkMatch/0 +-All/SearchPrefetchServiceEnabledBrowserTest.Back* +-All/SubframeSameFrameDownloadBrowserTest_AdFrame.Download* +-All/SubframeSameFrameDownloadBrowserTest_Sandbox.Download* +-All/SubresourceFilterWebSocketBrowserTest.BlockWebSocket/0 +-All/SubresourceFilterWebSocketBrowserTest.Do* +-All/TabCapturePerformanceTest.Performance* +-All/TopFrameSameFrameDownloadBrowserTest.Download* +-All/ViewSourceWithSplitCacheEnabledTest.NetworkIsolationKeyReusedForBackNavigation/0 +-All/ViewSourceWithSplitCacheTest.Http* +-All/WebAppConfirmViewBrowserTest.Invoke* +-AllForms/FormStructureBrowserTest.DataDrivenHeuristics/153 +-AllowlistedUrlDeepScanningBrowserTest.Allowlisted* +-AppBackgroundPageApiTest.NoJsBackgroundPage +-AppInfoDialogBrowserTest.InvokeUi_default +-AppSessionRestoreTest.Restore* +-AppViewTest.Test* +-AppWindowApiTest.On* +-AskGoogleForSuggestionsDialogTest.InvokeUi_default +-AuthenticatorDialogTest.Invoke* +-AuthenticatorDialogViewTest.Invoke* +-AutoPictureInPictureWindowControllerBrowserTest.AutoExitPictureInPictureIsTriggeredInRegularWebApp +-AutofillErrorDialogViewNativeViewsBrowserTest.Invoke* +-AutofillPopupBaseViewTest.CorrectBoundsTest +-AutofillProgressDialogViewsBrowserTest.InvokeUi +-AutomationApiTest.BoundsForRange +-AutomationApiTest.Events +-AutomationApiTest.Location2 +-AutomationApiTest.SanityCheck +-AvatarToolbarButtonBrowserTest.GuestWindowCount +-BackForwardCacheSiteDetailsBrowserTest.MemoryDetailsForBackForwardCache +-BackgroundAppBrowserTest.InstallBackgroundApp +-BackgroundFetchBrowserTest.DownloadService_Acceptance +-BackgroundFetchBrowserTest.Fetch* +-BackgroundFetchBrowserTest.Fetches* +-BackgroundFetchBrowserTest.Offline* +-BackgroundFetchBrowserTest.RecordBackgroundFetchUkmEvent +-BiMapTest.All +-BitmapFetcherBrowserTest.DataURLImage +-BitmapFetcherBrowserTest.StartTest +-BluetoothApiTest.Device* +-BluetoothApiTest.Discovery* +-BluetoothApiTest.Get* +-BluetoothChooserBrowserTest.Invoke* +-BluetoothPrivateApiTest.CancelPairing +-BluetoothPrivateApiTest.Connect +-BluetoothPrivateApiTest.DisconnectAll +-BluetoothPrivateApiTest.DiscoveryFilter +-BluetoothPrivateApiTest.ForgetDevice +-BluetoothPrivateApiTest.NoBluetoothAdapter +-BluetoothPrivateApiTest.Pair +-BluetoothPrivateApiTest.PasskeyPairing +-BluetoothPrivateApiTest.PincodePairing +-BluetoothPrivateApiTest.SetAdapterState +-BookmarkBrowsertest.HideStarOnNonbookmarkedInterstitial +-BookmarkBubbleViewBrowserTest.Invoke* +-BookmarkEditorViewBrowserTest.InvokeUi_all_tabs +-BookmarksListTest.All +-BreadcrumbManagerTabHelperBrowserTest.Download +-BreadcrumbManagerTabHelperSecurityStateBrowserTest.BrokenAuthentication +-BrowserActionApiTest.TestPictureInPictureOnBrowserActionIconClick +-BrowserCloseManagerBrowserTest.Test* +-BrowserFrameTest.DevToolsHasBoundsOnOpen +-BrowserFrameTest.WebAppsHasBoundsOnOpen +-BrowserNonClientFrameViewBrowserTest.Bookmark* +-BrowserNonClientFrameViewBrowserTest.BrowserFrameColorThemed +-BrowserNonClientFrameViewBrowserTest.CustomTabBarIsVisibleInFullscreen +-BrowserNonClientFrameViewBrowserTest.FullscreenForTabTitlebarHeight +-BrowserNonClientFrameViewBrowserTest.HTMLMetaThemeColorOverridesManifest +-BrowserTabRestoreTest.DelegateRestoreTabDisposition +-BrowserTabRestoreTest.RecentTabsMenuTabDisposition +-BrowserTest.DialogsDropFullscreen +-BrowserTest.DownloadDoesntDismissDialog +-BrowserTest.FaviconChange +-BrowserTest.FullscreenBookmarkBar +-BrowserTest.TestPopupBounds +-BrowserTestWithTabGroupsAutoCreateEnabled.SecondNewTabFromLinkWithSameDomainCreatesGroup +-BrowserViewTest.DevToolsUpdatesBrowserWindow +-BrowserViewTest.GetAccessibleTabModalDialogTitle +-BrowsingDataRemoverBrowserTest.Cache +-BrowsingDataRemoverBrowserTest.Database +-BrowsingDataRemoverBrowserTest.Download +-BrowsingDataRemoverBrowserTest.SessionOnlyStorageRemoved +-BrowsingDataRemoverBrowserTest.StorageRemovedFromDisk +-CRLSetBrowserTest.Test* +-CRLSetInterceptionBrowserTest.KnownInterceptionWorksOnHSTS +-CacheCounterTest.AfterDoom +-CacheCounterTest.Empty +-CacheCounterTest.NonEmpty +-CacheCounterTest.PeriodChanged +-CacheCounterTest.PrefChanged +-CaptivePortalBrowserTest.InterstitialTimerNavigateWhileLoading_EndWithSSLInterstitial +-CaptivePortalBrowserTest.SSLCertErrorLogin +-CaptivePortalBrowserTest.ShowCaptivePortalInterstitialOnCertError +-CardUnmaskAuthenticationSelectionDialogBrowserTest.InvokeUi_CardUnmaskAuthSelectionDialogDisplays +-CardUnmaskOtpInputDialogBrowserTest.InvokeUi_CardUnmaskOtpInputDialogDisplays +-CardUnmaskPromptViewBrowserTest.Invoke* +-CastDialogViewBrowserTest.Invoke* +-CastMirroringServiceHostBrowserTest.CaptureTabVideo +-CertVerifierBrowserTest.MockCertVerifierSmokeTest +-CertificateReportingServiceBrowserTest.Delayed* +-CertificateReportingServiceBrowserTest.DisableSafebrowsing +-CertificateReportingServiceBrowserTest.DontSendOldReports +-CertificateReportingServiceBrowserTest.DropOldReportsFromQueue +-CertificateReportingServiceBrowserTest.NotOptedIn_ShouldNotSendReports +-CertificateReportingServiceBrowserTest.OmitsCredentials +-CertificateReportingServiceBrowserTest.Opted* +-CertificateSelectorDialogTest.InvokeUi_default +-CertificateTransparencyPolicyTest.Certificate* +-CertificateTransparencySSLUITest.EnforcedAfterApril2018 +-ChromeAcceptHeaderTest.Check +-ChromeBackForwardCacheBrowserTest.DoNotShowSameSiteSubframeInTaskManager +-ChromeBackForwardCacheBrowserTest.DoesNotCacheIfPictureInPicture +-ChromeBackForwardCacheBrowserTest.Show* +-ChromeBrowserCloudManagementEnrollmentTest/ChromeBrowserCloudManagementEnrollmentTest.Test/1 +-ChromeBrowsingDataLifetimeManagerShutdownTest.BrowserShutdown +-ChromeMimeHandlerViewTest.MimeHandlerViewInDisplayNoneFrameForGoogleApps +-ChromeMojoProxyResolverFactoryBrowserTest.DestroyAndCreateService +-ChromeNavigationBrowserTest.CrossSiteRedirectionToPDF +-ChromeNavigationBrowserTest.OpenerNavigation_DownloadPolicy_Allowed +-ChromeNavigationBrowserTestWithMobileEmulation.CrossSiteRedirectionToPDFWithMobileEmulation +-ChromeNavigationBrowserTestWithMobileEmulation.NavigateToPDFWithMobileEmulation +-ChromeNetworkServiceMigrationBrowserTest.MigrateData +-ChromePasswordProtectionServiceBrowserWithFakeBackendPasswordStoreTest.SavedPassword +-ChromePasswordProtectionServiceSyncBrowserTest.GSuitePasswordAlertMode +-ChromeSitePerProcessPDFTest.EmbeddedPDFInsideCrossOriginFrame +-ChromeSitePerProcessTest.PopupWindowFocus +-ChromeSitePerProcessTest.TwoFingerTapContextMenu +-ChromeTracingDelegateBrowserTestFromCommandLine.IgnoreThrottle +-ChromeTracingDelegateBrowserTestFromCommandLine.ScenarioFromCommandLine +-ChromeURLDataManagerWebUITrustedTypesTest.No* +-ChromeUpdatesEventsApiTest.ChromeUpdates +-ClickModifierTest.Href* +-ClickModifierTest.Window* +-ClientHintsBrowserTest.Switch* +-CollectedCookiesTest.InvokeUi_default +-ColocatedPaymentManifestsTest.CanPay +-CommandServiceTest.Get* +-CommandServiceTest.Remove* +-CommonNameMismatchBrowserTest.NoCrashIfBothSubdomainsHaveCommonNameErrors +-CommonNameMismatchBrowserTest.WWWSubdomainMismatch_StopOnRedirects +-ConditionalCacheCountingHelperBrowserTest.Count +-ConfirmBubbleTest.InvokeUi_default +-ConnectionHelpTabHelperTest.CorrectlyExpandsCertErrorSection +-ConnectionHelpTabHelperTest.Interstitial* +-ConsumerDeepScanningBrowserTest.NonretriableErrorDoesNotShowModal +-ContentAnalysysDialogUiTest.InvokeUi_default +-ContentScriptApiTest.ContentScriptCSSLocalization +-ContentSettingBubbleDialogTest.Invoke* +-ContentVerifierPolicyTest.Backoff +-ContentVerifierPolicyTest.FailedUpdateRetries +-ContentVerifierPolicyTest.PolicyCorruptedOnStartup +-ContentVerifierTest.Content* +-ContentVerifierTest.DotSlashPaths +-ContentVerifierTest.ManualInstalledExtensionGotCorruptedThenForceInstalled +-ContentVerifierTest.PolicyCorrupted +-ContentVerifierTest.Remains* +-ContentVerifierTest.ResourceReadCancellationDoesNotFailVerification +-ContentVerifierTest.TamperLargeSizedResource +-ContentVerifierTest.Verification* +-ContextMenuBrowserTest.Gif* +-ContextMenuBrowserTest.JpgImageDownscaleToJpg +-ContextMenuBrowserTest.MenuContentsVerification_Subframe +-ContextMenuBrowserTest.Non* +-ContextMenuBrowserTest.OpenProfileNoneReferrer +-ContextMenuBrowserTest.PngImageOriginalDownscaleToPng +-ContextMenuBrowserTest.RealMenu +-ContextMenuBrowserTest.RequestPngForGifImage +-ContextMenuBrowserTest.SuggestedFileName +-ContinueWhereILeftOffTest.LocalStorageClearedOnExit +-ContinueWhereILeftOffTest.SessionCookies +-CookieControlsBubbleViewTest.Invoke* +-CookiePolicyBrowserTest.NestedFirstPartyIFrameStorageForFrame +-CrExtensionsA11yTestWithMultipleExensions.With* +-CrExtensionsManagerTestWithIdQueryParam.NavigationToDetails +-CrExtensionsManagerTestWithMultipleExtensionTypesInstalled.ChangePages +-CrExtensionsManagerTestWithMultipleExtensionTypesInstalled.ItemListVisibility +-CrExtensionsManagerTestWithMultipleExtensionTypesInstalled.NavigateToSitePermissionsSuccess +-CrExtensionsManagerTestWithMultipleExtensionTypesInstalled.PageTitleUpdate +-CrExtensionsManagerTestWithMultipleExtensionTypesInstalled.SplitItems +-CrExtensionsShortcutA11yTestWithExtensions.Shortcuts* +-CrManagementA11yTestWithExtension.Extension* +-CrSettingsAdvancedPageTest.Load +-CrSettingsCookiesPageTest.All +-CrSettingsPasswordsCheckTest.All +-CrSettingsPasswordsSectionTest.All +-CrSettingsPeoplePageTest.All +-CrSettingsSecurityPageTest.All +-CrSettingsSiteSettingsPageTest.All +-CreateAppShortcutDialogTest.InvokeUi_default +-CreativeOriginAdsPageLoadMetricsObserverBrowserTest.Creative* +-DeclarativeApiTest.ExtensionLifetimeRulesHandling +-DeclarativeApiTest.NoTracesAfterUninstalling +-DeepScanningFailureModalDialogTest.InvokeUi_default +-DefaultIsolation/TaskManagerOOPIFBrowserTest.CrossSiteIframeBecomesSameSite/0 +-DefaultIsolation/TaskManagerOOPIFBrowserTest.KillSubframe/0 +-DefaultIsolation/TaskManagerOOPIFBrowserTest.LeavePageWithCrossSiteIframes/0 +-DefaultIsolation/TaskManagerOOPIFBrowserTest.Navigate* +-DefaultIsolation/TaskManagerOOPIFBrowserTest.SubframeHistoryNavigation/0 +-DesktopCaptureApiTest.ChooseDesktopMedia +-DesktopCaptureApiTest.Delegation +-DesktopMediaPickerViewsBrowserTest.Invoke* +-DestroyProfileOnBrowserClose/ProfileHelperTestWithDestroyProfile.Delete* +-DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.Delete* +-DestroyProfileOnBrowserClose/ProfileManagerBrowserTest.Ephemeral* +-DevToolsAllowedByCommandLineSwitch.SwitchOverridesPolicyOnChromeOS +-DevToolsExtensionForceInstallTest.Policy* +-DevToolsNetInfoTest.EmulateNetworkConditions +-DevToolsProtocolTest.InputDispatchEventsToCorrectTarget +-DiceBrowserTest.Signout* +-DiceManageAccountBrowserTest.ClearManagedProfileOnStartup +-DiceWebSigninInterceptionBubbleBrowserTest.InvokeUi_default +-DiceWebSigninInterceptorBrowserTest.CloseSourceTab +-DiceWebSigninInterceptorBrowserTest.Switch* +-DiceWebSigninInterceptorEnterpriseBrowserTest.Enterprise* +-DidChangeVisibleSecurityStateTest.DidChangeVisibleSecurityStateObserverGoBack +-DiskCachesizeExperiment.ScaledCacheSize +-DownloadDangerPromptBrowserTest.Invoke* +-DownloadDeepScanningBrowserTest.Dangerous* +-DownloadDeepScanningBrowserTest.DlpAndMalwareViolations/0 +-DownloadDeepScanningBrowserTest.Failed* +-DownloadDeepScanningBrowserTest.Multiple* +-DownloadDeepScanningBrowserTest.Partial* +-DownloadDeepScanningBrowserTest.Password* +-DownloadDeepScanningBrowserTest.Safe* +-DownloadExtensionTest.Download* +-DownloadExtensionTest.Downloads* +-DownloadExtensionTest.FileExistenceCheckAfterSearch +-DownloadProtectionServiceBrowserTest.MultipartRarInspectionSecondPart +-DownloadProtectionServiceBrowserTest.Verify* +-DownloadRestrictionsDeepScanningBrowserTest.Reports* +-DownloadTest.AnchorDownloadTag +-DownloadTest.BrowserCloseAfterDownload +-DownloadTest.ChromeURLAfterDownload +-DownloadTest.Close* +-DownloadTest.CrossOriginRedirectDownloadFromAnchorDownload +-DownloadTest.Crx* +-DownloadTest.Dangerous* +-DownloadTest.Dont* +-DownloadTest.Download* +-DownloadTest.Feedback* +-DownloadTest.FileExistenceCheckOpeningDownloadsPage +-DownloadTest.KnownSize +-DownloadTest.MultipleDownloadsFromIframeSrcdoc +-DownloadTest.NewWindow +-DownloadTest.PerWindowShelf +-DownloadTest.Resumption* +-DownloadTest.SafeSupportedFile +-DownloadTest.Save* +-DownloadTest.SecurityLevels +-DownloadTest.TestMultipleDownloadsRequests +-DownloadTest.UnknownSize +-DownloadTest.UserScriptDownload +-DownloadTestSplitCacheEnabled.Save* +-DownloadTestWithFakeSafeBrowsing.NoUncommonDownloadReportWithoutUserProceed +-DownloadTestWithFakeSafeBrowsing.SendUncommonDownloadReportIfUserProceed +-EditAddressProfileDialogControllerImplTest.InvokeUi_Edit +-EmptyParametersTest.NoCrash +-EncryptedMediaSupportedTypesClearKeyTest.Video* +-EncryptedMediaSupportedTypesExternalClearKeyTest.EncryptionScheme +-EncryptedMediaSupportedTypesExternalClearKeyTest.Robustness +-EncryptedMediaSupportedTypesExternalClearKeyTest.SessionType +-EnterpriseStartupDialogViewBrowserTest.Invoke* +-ErrorPageAutoReloadTest.AutoReload +-ErrorPageAutoReloadTest.ManualReloadNotSuppressed +-EventPage/ManagementApiNonPersistentApiTest.UninstallSelf/0 +-EventsApiTest.ExtensionUpdateSendsOnInstalledEvent +-EventsApiTest.UpdateDispatchesOnInstalledAfterEnablement +-ExplicitlyAllowedNetworkPortsBackgroundFetchBrowserTest.UnblockedPortsDontThrow +-ExtensionApiTest.FileURLs +-ExtensionApiTest.Font* +-ExtensionApiTest.Shared* +-ExtensionApiTest.Storage +-ExtensionApiTest.WebSocket +-ExtensionApiTestWithManagementPolicy.ContentScriptPolicyByExtensionId +-ExtensionBackForwardCacheBlockedExtensionBrowserTest.ScriptDisallowed +-ExtensionBindingsApiTest.Web* +-ExtensionBrowserTest.BackgroundPageIsNeverComposited +-ExtensionBrowserTest.LoadChromeExtensionsWithOptionsParamWhenEmbedded +-ExtensionBrowserTest.OptionsPage +-ExtensionBrowserTest.RSSMultiRelLink +-ExtensionBrowserTest.RSSParse* +-ExtensionBrowserTest.SettingsOverridesDisallowed +-ExtensionBrowserTest.WebContents +-ExtensionCrxInstallerTest.AllowOffStore +-ExtensionCrxInstallerTest.AllowedThemeFileTypes +-ExtensionCrxInstallerTest.BlockedFileTypes +-ExtensionCrxInstallerTest.Blocklist +-ExtensionCrxInstallerTest.DoNotSync +-ExtensionCrxInstallerTest.Experimental* +-ExtensionCrxInstallerTest.HiDpiThemeTest +-ExtensionCrxInstallerTest.Install* +-ExtensionCrxInstallerTest.Non* +-ExtensionCrxInstallerTest.PackAndInstallExtensionFromDownload +-ExtensionCrxInstallerTest.Update* +-ExtensionCrxInstallerTestWithExperimentalApis.DoNotGrantScopes_WithCallback +-ExtensionCrxInstallerTestWithExperimentalApis.ExperimentalExtensionFromOutsideGalleryWithFlag +-ExtensionCrxInstallerTestWithExperimentalApis.Grant* +-ExtensionCrxInstallerTestWithExperimentalApis.PlatformAppCrx +-ExtensionDialogTest.TextInputViaKeyEvent +-ExtensionDisabledGlobalErrorTest.AcceptPermissions +-ExtensionDisabledGlobalErrorTest.HigherPermissionsFromSync +-ExtensionDisabledGlobalErrorTest.RemoteInstall +-ExtensionDisabledGlobalErrorTest.Uninstall* +-ExtensionDisabledGlobalErrorTest.UserDisabled +-ExtensionFunctionalTest.DownloadExtensionResource +-ExtensionFunctionalTest.TestSetExtensionsState +-ExtensionInstallBlockedDialogViewTest.Invoke* +-ExtensionInstallDialogRatingsSectionTest.RatingsSectionA11y +-ExtensionInstallDialogViewInteractiveBrowserTest.Invoke* +-ExtensionInstallFrictionDialogTest.InvokeUi_default +-ExtensionInstallUIBrowserTest.Test* +-ExtensionInstalledBubbleViewsBrowserTest.Invoke* +-ExtensionLoadingTest.KeepAliveWithDevToolsOpenOnReload +-ExtensionLoadingTest.Upgrade* +-ExtensionManagementApiBrowserTest.CreateAppShortcutConfirmDialog +-ExtensionManagementApiEscalationTest.DisabledReason +-ExtensionManagementApiEscalationTest.SetEnabled +-ExtensionManagementTest.Auto* +-ExtensionManagementTest.External* +-ExtensionManagementTest.Install* +-ExtensionManagementTest.PolicyOverridesUserInstall +-ExtensionOverrideTest.OverrideNewTabMultiple +-ExtensionPinningTest.IgnoreUpdateUrlInManifest +-ExtensionPinningTest.SelfHostedCWSExtensionNotUpdatedFromStore +-ExtensionPinningTest.Update* +-ExtensionPolicyTest.Corrupted* +-ExtensionPolicyTest.CrxVersionInconsistencyFromManifest +-ExtensionPolicyTest.Extension* +-ExtensionPolicyTest.Update* +-ExtensionPolicyTest2Contexts.ExtensionDefaultPolicyBlockedHost +-ExtensionStartupTest.NoFileAccess +-ExtensionTagsTest.Basic +-ExtensionUninstallDialogViewInteractiveBrowserTest.Invoke* +-ExtensionWebRequestApiIdentifiabilityTest.WebSocket +-ExtensionWebRequestApiTest.Web* +-ExtensionWebUITest.ReceivesExtensionOptionsOnClose +-ExtensionWebstoreGetWebGLStatusTest.Allowed +-ExtensionWebstorePrivateApiAllowlistEnforcementTest.EnhancedSafeBrowsingNotAllowlisted +-ExtensionWebstorePrivateApiAllowlistEnforcementTest.StandardSafeBrowsingNotAllowlisted +-ExtensionWebstorePrivateApiTest.AppInstallBubble +-ExtensionWebstorePrivateApiTest.EmptyCrx +-ExtensionWebstorePrivateApiTest.IconUrl +-ExtensionWebstorePrivateApiTest.IncorrectManifest2 +-ExtensionWebstorePrivateApiTest.Install* +-ExtensionWebstorePrivateApiTest.MissingDownloadDir +-ExtensionWindowCreateTest.AcceptState +-ExtensionsDisabledBrowserTest.TestStartupWithInstalledExtensions +-ExtensionsInternalsTest.TestExtensionsInternalsAreServed +-ExtensionsLoadMultipleTest.Test +-ExtensionsLoadTest.Test +-ExternalInstallErrorTest.TestShutdown +-ExternalProtocolDialogBrowserTest.InvokeUi_default +-ExternalProtocolDialogBrowserTest.TestFocus +-FencedFrameSiteDetailsBrowserTest.MemoryDetailsForFencedFrame +-FetchBehaviorTests/ContentVerifierHashTest.Default* +-FetchBehaviorTests/ContentVerifierHashTest.Fetch* +-FetchBehaviorTests/ContentVerifierHashTest.Tamper* +-FetchFLCodeDiscountWorkerBrowserTest.SimplePercentDiscountWithCodeTest +-FetchFLCodeDiscountWorkerBrowserTest.TwoCartsOneWithDiscountOneWithoutDiscount +-FetchFLCodelessDiscountWorkerBrowserTest.CartDiscountBecomeUnavailable +-FetchFLCodelessDiscountWorkerBrowserTest.NoDiscountForThisMerchantTest +-FetchFLCodelessDiscountWorkerBrowserTest.Simple* +-FetchFLCodelessDiscountWorkerBrowserTest.TwoCartsOneWithDiscountOneWithoutDiscount +-FileIFrameAPITest.FileAccessAllURLs +-FileSystemAccessBrowserTest.FullscreenOpenFile +-FileSystemAccessPermissionViewTest.Invoke* +-FileSystemAccessRestrictedDirectoryDialogViewTest.InvokeUi_default +-FileSystemAccessUsageBubbleViewTest.Invoke* +-FindInPageControllerTest.AudibleAlertsWithPrepopulatedFind +-FindInPageControllerTest.BigString +-FindInPageControllerTest.Find* +-FindInPageControllerTest.GlobalPasteboardIncognito +-FindInPageControllerTest.IncognitoFindNextSecret +-FindInPageControllerTest.LargePage +-FindInPageControllerTest.No* +-FindInPageControllerTest.PreferPreviousSearch +-FindInPageControllerTest.Prepopulate* +-FindInPageControllerTest.RestartSearchFromF3 +-FindInPageControllerTest.SelectChangesOrdinal_Issue20883 +-FindInPageControllerTest.StaleCountAfterNoResults +-FindInPageControllerTest.StartSearchAfterSelection +-FirstPartySetsWebSocketBrowserTest.SendsSamePartyCookies +-FlocInternalsBrowserTest.EmptyResponse +-FlocInternalsBrowserTest.Response* +-FolderUploadConfirmationViewTest.InitiallyFocusesCancel +-FolderUploadConfirmationViewTest.InvokeUi_default +-FullscreenControllerTest.FastKeyboardLockUnlockRelock +-FullscreenControllerTest.FullscreenOnFileURL +-FullscreenControllerTest.Keyboard* +-FullscreenControllerTest.Repeated* +-FullscreenControllerTest.SlowKeyboardLockUnlockRelock +-FuzzySearchTest.All +-GetAuthTokenFunctionTest.Interactive* +-GetAuthTokenFunctionTest.LoginInvalidatesTokenCache +-GetAuthTokenFunctionTest.Non* +-GlobalErrorBubbleTest.Invoke* +-HatsServiceProbabilityOne.AlsoShowsSettingsSurvey +-HatsServiceProbabilityOne.AlwaysShow +-HatsServiceProbabilityOne.CheckedAfterADayToShow +-HatsServiceProbabilityOne.DifferentMajorVersionShow +-HatsServiceProbabilityOne.DisallowsSameDelayedSurveyForWebContentsRequests +-HatsServiceProbabilityOne.Launch* +-HatsServiceProbabilityOne.ProfileOldEnoughToShow +-HatsServiceProbabilityOne.SameMajorVersionNoShow +-HatsServiceProbabilityOne.SingleHatsNextDialog +-HatsServiceProbabilityOne.Survey* +-HatsServiceProbabilityOne.VisibleWebContentsShow +-HelpBubbleFactoryViewsBrowsertest.InvokeUi_default +-HistoryBrowserTest.DownloadNoHistory +-HistoryManipulationInterventionBrowserTest.PDFDoNotSkipOnBackForwardDueToUserGesture +-HistoryManipulationInterventionBrowserTest.PDFSkipOnBackForwardNoUserGesture +-HttpProxyScriptBrowserTest.Verify +-HttpsEngagementPageLoadMetricsBrowserTest.UncommittedLoadWithError +-HttpsOnlyModeBrowserTest.HttpsUpgradeWithBrokenSSL_ShouldTriggerSSLInterstitial +-HttpsOnlyModeBrowserTest.UrlWithHttpsScheme_BrokenSSL_ShouldNotFallback +-I18nProcessTest.All +-IconLoaderBrowserTest.LoadGroup +-IconModuleTest.All +-IdentityInternalsMultipleTokensWebUITest.getAllTokens +-IdentityInternalsSingleTokenWebUITest.getAllTokens +-IdentityInternalsSingleTokenWebUITest.verifyGetters +-IframeCspTest.Show +-IgnorePaymentMethodTest.JITInstallablePHCannotMakePayments +-ImageAnnotationBrowserTest.ImageUrl +-ImageDecoderBrowserTest.Basic* +-ImageFetcherImplBrowserTest.NormalFetch +-ImportLockDialogViewBrowserTest.InvokeUi_default +-InMemoryApp/NetworkContextConfigurationDataPacBrowserTest.Data* +-InMemoryApp/NetworkContextConfigurationFilePacBrowserTest.File* +-InMemoryApp/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/1 +-InMemoryApp/NetworkContextConfigurationManagedProxySettingsBrowserTest.Max* +-InMemoryApp/NetworkContextConfigurationProxySettingsBrowserTest.Max* +-InProcessBrowserTest.ExternalConnectionFail +-InProcessBrowserTest.RunsScheduledLayoutOnAnchoredBubbles +-InProgressDownloadTest.ResumeInProgressDownloadBeforeLoadingHistory +-IncognitoBrowsingDataBrowserTest.Database +-IncognitoBrowsingDataBrowserTest.Download +-IncognitoBrowsingDataBrowserTest.StorageDoesntWriteToDisk +-IncognitoBrowsingDataBrowserTest.WebSqlDeletion +-IncognitoClearBrowsingDataDialogBrowserTest.InvokeUi_default +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationDataPacBrowserTest.Data* +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationFilePacBrowserTest.FilePac/1 +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.Http* +-IncognitoProfileMainNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.Max* +-InfiniteListTest.All +-InfoBarUiTest.InvokeUi_multiple_infobars +-InfoBarsTest.TestInfoBarsCloseOnNewTheme +-InlineLoginHelperBrowserTest.InvokeUi_default +-InlineLoginHelperBrowserTest.Signin* +-InlineLoginHelperBrowserTest.UntrustedSigninDialogCancel +-InlineLoginHelperBrowserTest.WithAuthCode +-IntentPickerDialogTest.InvokeUi_default +-InterstitialAccessibilityBrowserTest.TestSSLInterstitialAccessibility +-InterstitialUITest.BillingInterstitialQuiet +-InterstitialUITest.BlockedInterceptionInterstitial +-InterstitialUITest.CTInterstitial +-InterstitialUITest.Interstitial* +-InterstitialUITest.MITMSoftwareInterstitial +-InterstitialUITest.MalwareInterstitialQuiet +-InterstitialUITest.PhishingInterstitialQuiet +-InterstitialUITest.PinnedCertInterstitial +-InterstitialUITest.SSLInterstitial +-InterstitialUITest.UnwantedSoftwareInterstitialQuiet +-InterstitialUITest.UseCorrectWebContents +-JourneyLoggerTest.GooglePaymentApp +-JourneyLoggerTest.UKMCheckoutEventsNotRecordedForAppOriginWhenNoWindowShown +-JourneyLoggerTest.UKMTransactionAmountRecorded +-KioskModeTest.EnableKioskModeTest +-LargeStickyAdViolationBrowserTest.LargeStickyAd_AdInterventionTriggered +-LargeStickyAdViolationBrowserTest.NoLargeStickyAd_AdInterventionNotTriggered +-LargeStickyAdViolationBrowserTestWithoutEnforcement.LargeStickyAd_NoAdInterventionTriggered +-LoadImageBrowserTest.Load* +-LoadingPredictorBrowserTestWithOptimizationGuide.NavigationWithBothLocalPredictionAndOptimizationHint/3 +-LoadingPredictorBrowserTestWithProxy.Prepare* +-LoadingPredictorPrefetchBrowserTest.PrepareForPageLoadWithPredictionForPrefetchHasLocalHint/4 +-LoadingPredictorPrefetchCounterfactualBrowserTest.PrepareForPageLoadWithPredictionForPrefetchHasLocalHint/0 +-LocalCardMigrationBrowserTest.AcceptingDialogAddsLocalCardMigrationStrikes +-LocalCardMigrationBrowserTest.CardIdentifierString +-LocalCardMigrationBrowserTest.Clicking* +-LocalCardMigrationBrowserTest.Closed* +-LocalCardMigrationBrowserTest.Closing* +-LocalCardMigrationBrowserTest.CreditCardIconShownInLocationBar +-LocalCardMigrationBrowserTest.DialogContainsAllValidMigratableCard +-LocalCardMigrationBrowserTest.IntermediateMigrationOfferDoesNotShowWhenPaymentsDeclines +-LocalCardMigrationBrowserTest.RejectingDialogAddsLocalCardMigrationStrikes +-LocalCardMigrationBrowserTest.ReshowingBubbleDoesNotAddStrikes +-LocalCardMigrationBrowserTest.Reusing* +-LocalCardMigrationBrowserTest.UsingNewCardDoesNotShowIntermediateMigrationOffer +-LocalCardMigrationBrowserTestForStatusChip.ActivateFirstInactiveBubbleForAccessibility +-LocalCardMigrationBrowserTestForStatusChip.ClickingOmniboxIconReshowsBubble +-LocalCardMigrationBrowserTestForStatusChip.CreditCardIconShownInStatusChip +-LocalCardMigrationBrowserTestForStatusChip.IconAndBubbleVisibilityAfterTabSwitching +-ManagedConfigurationAPITest.AppRemovedFromPolicyList +-ManagedConfigurationAPITest.Data* +-ManagedConfigurationAPITest.Policy* +-ManagedConfigurationAPITest.UnknownKeys +-ManifestUpdateManagerAppIdentityBrowserTest.TestUpgradeDuringShutdownForAppIdentity +-ManifestUpdateManagerBrowserTest.Check* +-ManifestUpdateManagerCaptureLinksBrowserTest.CheckFindsCaptureLinksChange +-ManifestUpdateManagerHandleLinksBrowserTest.CheckFindsHandleLinksChange +-ManifestUpdateManagerIconUpdatingBrowserTest.CheckFindsIconUrlChange +-ManifestUpdateManagerLaunchHandlerBrowserTest.CheckFindsLaunchHandlerChange +-ManifestVerifierBrowserTest.OneSupportedOrigin +-ManifestVerifierBrowserTest.ThreeTypesOfMethods +-MediaEngagementBrowserTest.Do* +-MediaEngagementBrowserTest.IFrame* +-MediaEngagementBrowserTest.MultipleElements +-MediaEngagementBrowserTest.Record* +-MediaEngagementBrowserTest.Session* +-MediaEngagementPreloadBrowserTest.EnsureSingletonListIsLoaded +-MediaEngagementSessionRestoreBrowserTest.RestoredSession_Playback_MEI +-MediaFileValidatorTest.ValidImage +-MediaGalleriesInteractiveDialogTest.InvokeUi_DisplayDialog +-MediaHistoryForPrerenderBrowserTest.KeepRecordingMediaSession +-MediaHistoryOriginsWebUIBrowserTest.All +-MediaHistoryPlaybacksWebUIBrowserTest.All +-MediaHistoryStatsWebUIBrowserTest.All +-MediaSessionPictureInPictureWindowControllerBrowserTest.Next* +-MediaSessionPictureInPictureWindowControllerBrowserTest.Play* +-MediaSessionPictureInPictureWindowControllerBrowserTest.PreviousTrackHandlerCalled +-MediaSessionPictureInPictureWindowControllerBrowserTest.Skip* +-MediaSessionPictureInPictureWindowControllerBrowserTest.StopMediaSessionClosesPictureInPictureWindow +-MetadataCheckAndDeepScanningBrowserTest.Test* +-MimeHandlerViewTest.ActivatePostMessageSupportOnce +-MimeHandlerViewTest.BackgroundPage +-MimeHandlerViewTest.Basic +-MimeHandlerViewTest.Before* +-MimeHandlerViewTest.DataUrl +-MimeHandlerViewTest.DoNotLoadInSandboxedFrame +-MimeHandlerViewTest.Embed* +-MimeHandlerViewTest.Embedded* +-MimeHandlerViewTest.EmbedderFrameRemovedNoCrash +-MimeHandlerViewTest.Iframe +-MimeHandlerViewTest.NonAsciiHeaders +-MimeHandlerViewTest.PostMessage +-MimeHandlerViewTest.RejectPointLock +-MimeHandlerViewTest.SingleRequest +-MimeHandlerViewTest.TargetBlankAnchor +-MouseLockControllerTest.Mouse* +-MyIpAddressProxyScriptBrowserTest.Verify +-NavigationConsumingTest.NavigationConsumesUserGesture_Fullscreen +-NavigationPredictorBrowserTest.ClickAnchorElement +-NavigationPredictorBrowserTest.MultipleNavigations +-NavigationPredictorBrowserTest.Page* +-NavigationPredictorBrowserTest.Pipeline +-NavigationPredictorBrowserTest.Single* +-NavigationPredictorBrowserTest.TwoObservers +-NavigationPredictorBrowserTest.ViewportOnlyAndUrlIncrementByOne +-NavigationPredictorPrerenderBrowserTest.PrerenderingDontCreatePredictor +-NetworkQualityEstimatorPrefsBrowserTest.ReadPrefsAtStartupCustomPrefFile +-NetworkingPrivateServiceClientApiTest.On* +-NetworkingPrivateServiceClientApiTest.RequestNetworkScan +-NewTabPageAppTest.Clicks +-NewTabPageAppTest.CounterfactualModules +-NewTabPageAppTest.CustomizeUrl +-NewTabPageAppTest.Misc +-NewTabPageAppTest.Modules +-NewTabPageAppTest.Promo +-NewTabPageAppTest.Theming +-NewTabPageBackgroundManagerTest.All +-NewTabPageCustomizeBackgroundsTest.All +-NewTabPageCustomizeDialogTest.All +-NewTabPageCustomizeModulesTest.All +-NewTabPageCustomizeShortcutsTest.All +-NewTabPageDoodleShareDialogTest.All +-NewTabPageLogoTest.All +-NewTabPageMetricsUtilsTest.All +-NewTabPageMiddleSlotPromoTest.All +-NewTabPageModulesChromeCartV2ModuleTest.All +-NewTabPageModulesDriveModuleTest.All +-NewTabPageModulesDriveV2ModuleTest.All +-NewTabPageModulesDummyModuleTest.All +-NewTabPageModulesInfoDialogTest.All +-NewTabPageModulesModuleDescriptorTest.All +-NewTabPageModulesModuleHeaderTest.All +-NewTabPageModulesModuleRegistryTest.All +-NewTabPageModulesModuleWrapperTest.All +-NewTabPageModulesModulesTest.All +-NewTabPageModulesPhotosModuleTest.All +-NewTabPageModulesRecipesV2ModuleTest.All +-NewTabPageRealboxTest.All +-NewTabPageTest.LandingPagePixelTest +-NewTabPageVoiceSearchOverlayTest.All +-NoSessionRestoreTest.CookiesClearedOnExit +-NoSessionRestoreTest.LocalStorageClearedOnStartup +-NoSessionRestoreTestWithStartupDeletionDisabled.CookiesClearedOnStartup +-NoStatePrefetchBrowserTest.OpenTaskManager +-NoStatePrefetchBrowserTest.PrefetchCookieCrossDomainSameSiteStrict +-OCSPBrowserTest.HardFailOnOCSPInvalid +-OCSPBrowserTest.Test* +-OmniboxPopupContentsViewTest.ClickOmnibox +-OmniboxPopupContentsViewTest.PopupMatchesLocationBarBackground +-OmniboxSuggestionButtonRowBrowserTest.InvokeUi +-OnDiskApp/NetworkContextConfigurationBrowserTest.Cache/0 +-OnDiskApp/NetworkContextConfigurationBrowserTest.Cookies* +-OnDiskApp/NetworkContextConfigurationBrowserTest.DiskCache/0 +-OnDiskApp/NetworkContextConfigurationDataPacBrowserTest.Data* +-OnDiskApp/NetworkContextConfigurationFilePacBrowserTest.FilePac/0 +-OnDiskApp/NetworkContextConfigurationHttpPacBrowserTest.HttpPac/0 +-OnDiskApp/NetworkContextConfigurationManagedProxySettingsBrowserTest.Max* +-OnDiskApp/NetworkContextConfigurationProxySettingsBrowserTest.Max* +-OnDiskApp/NetworkContextConfigurationReportingAndNelBrowserTest.PersistReportingAndNel/0 +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationFilePacBrowserTest.File* +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationHttpPacBrowserTest.Http* +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationManagedProxySettingsBrowserTest.Max* +-OnDiskAppWithIncognitoProfile/NetworkContextConfigurationProxySettingsBrowserTest.Max* +-OutOfMemoryReporterPrerenderBrowserTest.NotReportedOnPrerenderPage +-OutdatedUpgradeBubbleTest.Invoke* +-OverlayPopupAdViolationBrowserTest.NoOverlayPopupAd_AdInterventionNotTriggered +-OverlayPopupAdViolationBrowserTest.OverlayPopupAd_AdInterventionTriggered +-OverlayPopupAdViolationBrowserTestWithoutEnforcement.OverlayPopupAd_NoAdInterventionTriggered +-OverrideLanguagePrefsForAutoHrefTranslateBrowserTest.HrefTranslateOverrideForAutoTranslate +-OverrideLanguagePrefsForUiOnlyHrefTranslateBrowserTest.HrefTranslateOverrideForTranslateUi +-OverrideSitePrefsForAutoHrefTranslateBrowserTest.HrefTranslateOverrideForAutoTranslate +-OverrideSitePrefsForUiOnlyHrefTranslateBrowserTest.HrefTranslateOverrideForTranslateUi +-PKPModelClientTest.PKPEnforced +-PageInfoBubbleViewAboutThisSiteDialogBrowserTest.Invoke* +-PageInfoBubbleViewDialogBrowserTest.Invoke* +-PageInfoBubbleViewHistoryDialogBrowserTest.InvokeUi_History +-PageLoadMetricsBrowserTest.CachedPage +-PageLoadMetricsBrowserTest.IgnoreDownloads +-PageLoadMetricsBrowserTest.Input* +-PageLoadMetricsBrowserTest.Main* +-PageLoadMetricsBrowserTest.PayloadSizeIgnoresDownloads +-PageLoadMetricsBrowserTestWithAnimatedLCPFlag.Page* +-PageLoadMetricsBrowserTestWithAutoupgradesDisabled.Use* +-PageLoadMetricsBrowserTestWithBackForwardCache.UseCounterUkmFeaturesLoggedOnBFCacheEviction +-PageLoadMetricsBrowserTestWithRuntimeAnimatedLCPFlag.PageLCPAnimatedImageOnlyRuntimeFlag +-PageTextObserverBrowserTest.OOPIFAMPSubframe +-PageTextObserverSingleProcessBrowserTest.Same* +-PasswordBubbleBrowserTest.Invoke* +-PasswordDialogViewTest.Invoke* +-PasswordGenerationPopupViewTest.CloseWebContentsWithVisiblePopup +-PasswordManagerBrowserTest.DeleteCredentialsUpdateDropdown +-PasswordManagerBrowserTest.InFrameNavigationDoesNotClearPopupState +-PasswordManagerBrowserTest.PasswordValueAccessibleOnSubmit +-PasswordManagerBrowserTest.SameOriginIframeAutoFillTest +-PasswordManagerDialogBrowserTest.InvokeUi_normal +-PasswordReuseModalWarningTest.InvokeUi_default +-PasswordsPrivateApiTest.Get* +-PaymentHandlerIconRefetchTest.RefetchMissingIcon +-PaymentHandlerInstallFailedTest.Test +-PaymentHandlerJitInstallWithRegisteredSwTest.CanJitInstallPaymentHandlerWhenServiceWorkerIsAlreadyInstalled +-PaymentHandlerJustInTimeInstallationTest.Install* +-PaymentHandlerSkipSheetTest.NoSkipWithoutUserGesture +-PaymentHandlerSkipSheetTest.SkipWithUserGesture +-PaymentManifestParserTest.UrlsAndOrigins +-PaymentManifestParserTest.WebAppManifest +-PaymentMethodViewControllerTest.DoNotShowAddCardWhenBasicCardIsNotSupported +-PaymentRequestCanMakePaymentMetricsWithBasicCardDisabledTest.Called* +-PaymentRequestCanMakePaymentQueryBasicCardDisabledTest.CanMakePayment_NotSupported +-PaymentRequestCvcUnmaskViewControllerVisualTest.InvokeUi_default +-PaymentRequestModifiersTest.Modifier* +-PaymentRequestModifiersTest.No* +-PaymentRequestNoUpdateWithBasicCardDisabledTest.BuyWithoutPromises +-PaymentRequestNoUpdateWithTest.BuyWithoutPromises +-PaymentRequestOrderSummaryViewControllerBasicCardDisabledTest.OrderSummaryReflectsShippingOption +-PaymentRequestOrderSummaryViewControllerTest.OrderSummaryReflectsShippingOption +-PaymentRequestPaymentAppTest.ReadSupportedDelegationsFromAppManifest +-PaymentRequestShippingOptionViewControllerBasicCardDisabledTest.SelectingVariousShippingOptions +-PaymentRequestShippingOptionViewControllerTest.SelectingVariousShippingOptions +-PaymentRequestShowPromiseTest.CannotShipError +-PaymentRequestShowPromiseTest.Resolve* +-PaymentRequestShowPromiseTest.Single* +-PaymentRequestUpdateWithBasicCardEnabledTest.Update* +-PaymentRequestUpdateWithWithBasicCardDisabledTest.Update* +-PaymentsRequestVisualTest.InvokeUi_NoShipping +-PaymentsRequestVisualWithBasicCardDisabledTest.InvokeUi_NoShipping +-PermissionsApiTest.FileLoad +-PersistentBackground/ExtensionApiCaptureTest.Capture* +-PersistentBackground/ExtensionI18nTest.Basic/0 +-PersistentBackground/ExtensionManagementApiTest.Basics/0 +-PersistentBackground/ExtensionManagementApiTest.NoPermission/0 +-PersistentBackground/ExtensionPageCaptureApiTest.SaveAsMHTMLWithFileAccess/0 +-PersistentBackground/InstallReplacementWebAppApiTest.Installable* +-PersistentBackground/InstallReplacementWebAppApiTest.NoGesture/0 +-PersistentBackground/InstallReplacementWebAppApiTest.NotInstallableWebApp/0 +-PersistentBackground/PageActionBrowserTest.PageAction/0 +-PersistentBackground/PageActionBrowserTest.UnloadPageAction/0 +-PersistentBackground/RuntimeApiTest.GetPlatformInfo/0 +-PersistentBackground/WebNavigationApiTestWithContextType.Download/0 +-PersistentBackground/WebNavigationApiTestWithContextType.RequestOpenTab/0 +-PersistentBackground/WebNavigationApiTestWithContextType.Target* +-PictureInPictureLazyBackgroundPageApiTest.PictureInPictureInBackgroundPage +-PictureInPicturePixelComparisonBrowserTest.PlayAndPauseControls +-PictureInPicturePixelComparisonBrowserTest.VideoPlay +-PictureInPictureWindowControllerBrowserTest.Close* +-PictureInPictureWindowControllerBrowserTest.CreationAndVisibilityAndActivation +-PictureInPictureWindowControllerBrowserTest.CrossOriginFrameEnterLeaveCloseWindow +-PictureInPictureWindowControllerBrowserTest.Enter* +-PictureInPictureWindowControllerBrowserTest.ExitFireEventAndCallbackWhenNoSource +-PictureInPictureWindowControllerBrowserTest.FrameEnterLeaveClosesWindow +-PictureInPictureWindowControllerBrowserTest.MultipleBrowserWindowOnePIPWindow +-PictureInPictureWindowControllerBrowserTest.Open* +-PictureInPictureWindowControllerBrowserTest.PageVisibilityEventsFiredWhenPictureInPicture +-PictureInPictureWindowControllerBrowserTest.Picture* +-PictureInPictureWindowControllerBrowserTest.Play* +-PictureInPictureWindowControllerBrowserTest.PreloadNoneSrcChangeThenLoad +-PictureInPictureWindowControllerBrowserTest.RequestPictureInPictureTwiceFromSameVideo +-PictureInPictureWindowControllerBrowserTest.ResetVideoSrcKeepsPictureInPictureWindowOpened +-PictureInPictureWindowControllerBrowserTest.ResizeEventFired +-PictureInPictureWindowControllerBrowserTest.SpaceKeyTogglePlayPause +-PictureInPictureWindowControllerBrowserTest.TabIconUpdated +-PictureInPictureWindowControllerBrowserTest.UpdateVideoSrcKeepsPictureInPictureWindowOpened +-PictureInPictureWindowControllerBrowserTest.VideoWithNoAudioPausedWhenHiddenResumesPlayback +-PictureInPictureWindowControllerFencedFrameBrowserTest.FencedFrameShouldNotCloseWindow +-PictureInPictureWindowControllerPrerenderBrowserTest.EnterPipThenNavigateAwayCloseWindow +-PolicyAppParameterizedTest/ManifestUpdateManagerBrowserTest_PolicyAppsCanUpdate.CheckDoesApplyIconURLChangeForPolicyAppsWithFlag/0 +-PolicyPrefsTestCoverageTest.AllPoliciesHaveATestCase +-PolicyTest.DefaultCookiesSetting +-PolicyTest.DownloadDirectory +-PolicyTest.WebsiteCookiesSetting +-PolicyTestWindowOpener.CheckWindowOpenerNonNull +-PolicyUpdateServiceTest.Backoff +-PolicyUpdateServiceTest.FailedUpdateRetries +-PolicyUpdateServiceTest.PolicyCorruptedOnStartup +-PortalBrowserTest.Task* +-PrefHashBrowserTestChangedSplitPref.ChangedSplitPref +-PrefHashBrowserTestUnchangedCustom.UnchangedCustom +-PrefetchBrowserTest.Prefetch* +-PrefsFunctionalTest.TestDownloadDirPref +-PreinstalledAppsMigrationBrowserTest.Test* +-PreinstalledAppsMigrationEnabledThenRolledBackBrowserTest.TestAppInstalled +-PreinstalledWebAppManagerExtensionBrowserTest.UninstallAndReplace +-PreinstalledWebAppMigratePlatformAppBrowserTest.MigratePlatformAppPreferences +-PreinstalledWebAppMigrationBrowserTest.AppToReplaceStillInstalled +-PreinstalledWebAppMigrationBrowserTest.Migrate* +-PreinstalledWebAppMigrationBrowserTest.UserUninstalledExtensionApp +-PrerenderSiteDetailsBrowserTest.MemoryDetailsForPrerender +-PresentationReceiverWindowControllerBrowserTest.CreatesWindow +-PresentationReceiverWindowControllerBrowserTest.WindowClosingTerminatesPresentation +-PresentationReceiverWindowViewBrowserTest.LocationBarViewShown +-PresentationReceiverWindowViewBrowserTest.ShowPageInfoDialog +-PreservedWindowPlacement.Test +-PrivacyBudgetFieldtrialConfigTest.LoadsSettingsFromFieldTrialConfig +-PrivacySandboxTest.All +-PrivateNetworkAccessAutoReloadBrowserTest.AutoReloadWorks +-ProcessManagerBrowserTest.BlobURLDownloadsToExtensionAllowed +-ProcessMemoryMetricsEmitterTest.Fetch* +-ProcessMemoryMetricsEmitterTest.ForegroundAndBackgroundPages +-ProfileCustomizationBubbleBrowserTest.IPH +-ProfileCustomizationBubbleBrowserTest.InvokeUi_default +-ProfileHelperTest.OpenNewWindowForProfile +-ProfileMainNetworkContext/NetworkContextConfigurationBrowserTest.Cache* +-ProfileMainNetworkContext/NetworkContextConfigurationBrowserTest.Cookies* +-ProfileMainNetworkContext/NetworkContextConfigurationBrowserTest.Disk* +-ProfileMainNetworkContext/NetworkContextConfigurationDataPacBrowserTest.Data* +-ProfileMainNetworkContext/NetworkContextConfigurationFilePacBrowserTest.File* +-ProfileMainNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.Http* +-ProfileMainNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.Max* +-ProfileMainNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.Max* +-ProfileMainNetworkContext/NetworkContextConfigurationReportingAndNelBrowserTest.Persist* +-ProfileMenuClickTest_MultipleProfiles.Profile* +-ProfileMenuClickTest_SyncError.Profile* +-ProfileMenuClickTest_WithUnconsentedPrimaryAccount.Profile* +-ProfileMenuViewExtensionsTest.CloseIPH +-ProfileMenuViewExtensionsTest.ThemeChanged +-ProfileNetworkContextServiceBrowsertest.DefaultCacheSize +-ProfileSigninConfirmationDialogTest.InvokeUi_default +-ProfileWindowBrowserTest.OpenBrowserWindowForProfileWithSigninRequired +-PromptForScanningModalDialogTest.InvokeUi_default +-ProxyBrowserTest.BasicAuthWSConnect +-ProxyBrowserTest.ProxyAuthHTTPS +-ProxySettingsApiTest.ProxyEventsParseError +-QRCodeGeneratorBubbleBrowserTest.Invoke* +-ReadLaterButtonBrowserTest.InvokeUi_default +-ReaderModeIconViewBrowserTest.NonSecurePagesNotDistillable +-RedirectTest.ClientCancelled +-ReferrerPolicyCapReferrerToOriginOnCrossOriginTest.Honors* +-ReferrerPolicyCapReferrerToOriginOnCrossOriginTest.RespectsNoReferrerPref +-ReferrerPolicyTest.Context* +-ReferrerPolicyTest.History +-ReferrerPolicyTest.Http* +-ReferrerPolicyTest.Https* +-ReferrerPolicyTest.Left* +-ReferrerPolicyTest.Middle* +-ReferrerPolicyTest.RequestTabletSite +-ReferrerPolicyTest.Target* +-RelaunchRecommendedBubbleViewDialogTest.InvokeUi_default +-RelaunchRequiredDialogViewDialogTest.InvokeUi_default +-RemoteCopyBrowserTest.ImageUrl +-RemoteCopyBrowserTest.Text* +-RemoveLocalAccountTest.ShouldNotifyObservers +-RepostFormWarningTest.InvokeUi_TestRepostWarning +-RestartTest.CookiesClearedOnExit +-RestartTest.SessionCookies +-RestoreOnStartupPolicyTestInstance/RestoreOnStartupPolicyTest.Run* +-RuntimeAPIUpdateTest.TerminatedExtensionUpdateHasCorrectPreviousVersion +-SCTReportingServiceBrowserTest.NoValidSCTsNoReport +-SSLBlockingPageIDNTest.SSLBlockingPageDecodesIDN +-SSLFencedFrameBrowserTest.InAppTestProceededBadCertPageInFencedFrame +-SSLNetworkTimeBrowserTest.CloseTabBeforeNetworkFetchCompletes +-SSLNetworkTimeBrowserTest.On* +-SSLNetworkTimeBrowserTest.TimeoutExpiresBeforeFetchCompletes +-SSLPKPBrowserTest.SendPKPReport +-SSLUIAutoReloadTest.AutoReloadDisabled +-SSLUICaptivePortalListDisabledTest.Disabled +-SSLUICaptivePortalListResourceBundleTest.Enabled* +-SSLUIDynamicInterstitialTest.Mismatch* +-SSLUIMITMSoftwareDisabledTest.DisabledWithFinch +-SSLUIMITMSoftwareEnabledTest.Certificate* +-SSLUIMITMSoftwareEnabledTest.EnabledWithFinch +-SSLUIMITMSoftwareEnabledTest.EnterpriseManaged +-SSLUIMITMSoftwareEnabledTest.NonMatchingCertificate_NoMITMSoftwareInterstitial +-SSLUIMITMSoftwareEnabledTest.NotEnterpriseManaged +-SSLUIMITMSoftwareEnabledTest.OverridableError_NoMITMSoftwareInterstitial +-SSLUIMITMSoftwareEnabledTest.TwoCertErrors_NoMITMSoftwareInterstitial +-SSLUIMITMSoftwareEnabledTest.WrongCertError_NoMITMSoftwareInterstitial +-SSLUITest.Bad* +-SSLUITest.DisplayedContentWithCertErrorsClearedOnNavigation +-SSLUITest.ErrorPage +-SSLUITest.InAppTestHTTPSExpiredCertAndPreviouslyProceeded +-SSLUITest.InterstitialNotAffectedByHideShow +-SSLUITest.MixedContentHistogramNotLoggedForSiteWithBadCertificate +-SSLUITest.NetworkErrorDoesntRevokeExemptions +-SSLUITest.ProceedLinkOverridable +-SSLUITest.SHA1IsDefaultDisabled +-SSLUITest.SSLStatus* +-SSLUITest.SimpleURLLoaderCertError +-SSLUITest.Test* +-SSLUITestHSTS.TestInterstitialOptionsNonOverridable +-SSLUITestIgnoreCertErrors.TestWSS +-SSLUITestIgnoreCertErrorsBySPKIWSS.TestWSSExpired +-SSLUITestWithCaptivePortalInterstitialDisabled.OSReportsCaptivePortal_FeatureDisabled +-SSLUITestWithEnhancedProtectionMessage.Verify* +-SSLUITestWithExtendedReporting.Test* +-SafeBrowsingBlockingPageBrowserTestWithThreatTypeAndIsolationSetting/SafeBrowsingBlockingPageBrowserTest.Security* +-SafeBrowsingBlockingPageWithDelayedWarningsBrowserTest/SafeBrowsingBlockingPageDelayedWarningBrowserTest.Fullscreen* +-SafeBrowsingBlockingPageWithDelayedWarningsBrowserTest/SafeBrowsingBlockingPageDelayedWarningBrowserTest.Key* +-SafeBrowsingNetworkContext/NetworkContextConfigurationBrowserTest.CookiesEnabled/1 +-SafeBrowsingNetworkContext/NetworkContextConfigurationDataPacBrowserTest.DataPac/0 +-SafeBrowsingNetworkContext/NetworkContextConfigurationFilePacBrowserTest.FilePac/0 +-SafeBrowsingNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.Http* +-SafeBrowsingNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.Max* +-SafeBrowsingNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.Max* +-SafeBrowsingPolicyTest.SSLError* +-SafeBrowsingPolicyTest.SafeBrowsingStatePolicyManaged +-SafeXmlParserTest.Parse +-SafetyTipPageInfoBubbleViewDialogTest.Invoke* +-SaveAsCompleteHtml/SavePageOriginalVsSavedComparisonTest.BrokenImage/0 +-SaveAsCompleteHtml/SavePageOriginalVsSavedComparisonTest.Cross* +-SaveAsCompleteHtml/SavePageOriginalVsSavedComparisonTest.Encoding/0 +-SaveAsCompleteHtml/SavePageOriginalVsSavedComparisonTest.NestedFrames/0 +-SaveAsCompleteHtml/SavePageOriginalVsSavedComparisonTest.RuntimeChanges/0 +-SaveAsCompleteHtml/SavePageOriginalVsSavedComparisonTest.Style/0 +-SaveAsMhtml/SavePageOriginalVsSavedComparisonTest.AboutBlank/0 +-SaveAsMhtml/SavePageOriginalVsSavedComparisonTest.BrokenImage/0 +-SaveAsMhtml/SavePageOriginalVsSavedComparisonTest.Cross* +-SaveAsMhtml/SavePageOriginalVsSavedComparisonTest.NestedFrames/0 +-SaveAsMhtml/SavePageOriginalVsSavedComparisonTest.RuntimeChanges/0 +-SaveAsMhtml/SavePageOriginalVsSavedComparisonTest.Style/0 +-SaveCardBubbleControllerImplTest.Invoke* +-SaveCardBubbleViewsFullFormBrowserTest.AlertAccessibleEvent +-SaveCardBubbleViewsFullFormBrowserTest.Local_ClickingNoThanksClosesBubble +-SaveCardBubbleViewsFullFormBrowserTest.StrikeDatabase_Local_AddStrikeIfBubbleDeclined +-SaveCardBubbleViewsFullFormBrowserTestForManageCard.Local* +-SaveCardBubbleViewsFullFormBrowserTestForStatusChip.ActivateFirstInactiveBubbleForAccessibility +-SaveCardBubbleViewsFullFormBrowserTestForStatusChip.ClickingOnCreditCardIconInStatusChipReshowsBubble +-SaveCardBubbleViewsFullFormBrowserTestForStatusChip.CreditCardIconShownInStatusChip +-SaveCardBubbleViewsFullFormBrowserTestForStatusChip.Feedback_Success +-SaveCardBubbleViewsFullFormBrowserTestForStatusChip.IconAndBubbleVisibilityAfterTabSwitching +-SaveCardBubbleViewsFullFormBrowserTestSettings.Local_ManageCardsButtonRedirects +-SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream.Local* +-SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream.Logic* +-SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream.StrikeDatabase_Upload_AddStrikeIfBubbleDeclined +-SaveCardBubbleViewsFullFormBrowserTestWithAutofillUpstream.Upload* +-SaveCardBubbleViewsSyncTransportFullFormBrowserTest.Local_TransportMode_InfoTextIconDoesNotExist +-SaveCardBubbleViewsSyncTransportFullFormBrowserTest.Upload* +-SavePackageDeepScanningBrowserTest.Allowed +-SavePackageDeepScanningBrowserTest.Blocked +-SavePackageDeepScanningBrowserTest.DiscardAfterWarning +-SavePackageDeepScanningBrowserTest.KeepAfterWarning +-SavePackageDeepScanningBrowserTest.OpenNow +-SavePageBrowserTest.DangerousSubresources +-SavePageBrowserTest.FileNameFromPageTitle +-SavePageBrowserTest.RemoveFromList +-SavePageBrowserTest.Save* +-SavePageBrowserTest.SecurityLevelHistogram +-SavePageSitePerProcessBrowserTest.CompleteHtmlWhenRendererIsDead +-SavePageSitePerProcessBrowserTest.SaveAsMHTML +-SaveUPIBubbleControllerImplTest.InvokeUi +-SaveUpdateAddressProfileBubbleControllerImplTest.CloseTabWhileBubbleIsOpen +-SaveUpdateAddressProfileBubbleControllerImplTest.Invoke* +-SearchByImageBrowserTest.ImageSearchWithValidImage +-SearchByImageBrowserTest.LensImageSearchWithValidImage +-SecurePaymentConfirmationDialogViewTest.InvokeUi_default +-SecurityStatePageLoadMetricsBrowserTest.UncommittedLoadWithError +-SecurityStateTabHelperPrerenderTest.InvalidPrerender +-SecurityStateTabHelperTest.SHA1CertificateBlocked +-SecurityStateTabHelperTest.UMALogs* +-SecurityStateTabHelperTestWithAutoupgradesDisabled.BrokenHTTPS +-SendTabToSelfBubbleTest.InvokeUi_default +-ServiceWorker/ExtensionApiCaptureTest.CaptureVisibleTabJpeg/0 +-ServiceWorker/ExtensionManagementApiTest.Basics/0 +-ServiceWorker/ExtensionManagementApiTest.NoPermission/0 +-ServiceWorker/ExtensionPageCaptureApiTest.Save* +-ServiceWorker/InstallReplacementWebAppApiTest.Installable* +-ServiceWorker/InstallReplacementWebAppApiTest.NoGesture/0 +-ServiceWorker/InstallReplacementWebAppApiTest.NotInstallableWebApp/0 +-ServiceWorker/PageActionBrowserTest.PageAction/0 +-ServiceWorker/PageActionBrowserTest.UnloadPageAction/0 +-ServiceWorker/RuntimeApiTest.GetPlatformInfo/0 +-ServiceWorker/WebNavigationApiTestWithContextType.Download/0 +-ServiceWorker/WebNavigationApiTestWithContextType.RequestOpenTab/0 +-ServiceWorker/WebNavigationApiTestWithContextType.Target* +-ServiceWorkerBasedBackgroundTest.EventsAfterRestart +-ServiceWorkerBasedBackgroundTest.FilteredEventsAfterRestart +-ServiceWorkerBasedBackgroundTest.UpdatePackedExtension +-ServiceWorkerBasedBackgroundTest.WindowsBasic +-ServiceWorkerPaymentAppFinderBrowserTest.Cross* +-ServiceWorkerPaymentAppFinderBrowserTest.InstallablePaymentApp +-ServiceWorkerPaymentAppFinderBrowserTest.SupportedOrigin +-ServiceWorkerPaymentAppFinderBrowserTest.ThreeRedirectsIsValid +-ServiceWorkerPaymentAppFinderBrowserTest.Two* +-ServiceWorkerTest.MimeHandlerView +-ServiceWorkerTest.Update* +-SessionCrashedBubbleViewTest.Invoke* +-SessionRestoreTest.NormalAndPopup +-SessionRestoreTest.RestoreAfterClosingTabbedBrowserWithAppAndLaunching +-SessionRestoreTest.TabWithDownloadDoesNotGetRestored +-SettingsA11yBasicV3.Basic* +-SettingsA11yEditDictionaryV3.Edit* +-SettingsOverriddenDialogViewBrowserTest.Invoke* +-SettingsOverriddenParamsProvidersBrowserTest.DialogParamsWithNonDefaultSearch +-SharedArrayBufferTest.Transfer* +-SharedClipboardBrowserTest.Context* +-SharedClipboardUIFeatureDisabledBrowserTest.ContextMenu_UIFeatureDisabled +-SharedHighlightingBrowserTest.LinkGenerationTest +-SidePanelBookmarksListTest.All +-SignedExchangePolicyTest.SignedExchangeDisabled +-SigninInterceptFirstRunExperienceDialogBrowserTest.AcceptSync +-SigninInterceptFirstRunExperienceDialogBrowserTest.SyncDisabled +-SigninReauthTest.Dialog +-SitePerProcess/TaskManagerOOPIFBrowserTest.CrossSiteIframeBecomesSameSite/0 +-SitePerProcess/TaskManagerOOPIFBrowserTest.KillSubframe/0 +-SitePerProcess/TaskManagerOOPIFBrowserTest.LeavePageWithCrossSiteIframes/0 +-SitePerProcess/TaskManagerOOPIFBrowserTest.Navigate* +-SitePerProcess/TaskManagerOOPIFBrowserTest.SubframeHistoryNavigation/0 +-SitePerProcessHighDPIExpiredCertBrowserTest.InterstitialLoadsWithCorrectDeviceScaleFactor +-SmartSessionRestoreTest.CorrectLoadingOrder +-SocketApiTest.SocketMulticast +-SpellcheckServiceBrowserTest.DeleteCorruptedBDICT +-StartupHelperBrowserTest.ValidateCrx +-StartupMetricsTest.ReportsValues +-SubAppsServiceImplBrowserTest.EndToEndAdd +-SyncAwareCounterTest.AutofillCounter +-SyncAwareCounterTest.HistoryCounter +-SyncAwareCounterTest.PasswordCounter +-SystemNetworkContext/NetworkContextConfigurationDataPacBrowserTest.Data* +-SystemNetworkContext/NetworkContextConfigurationFilePacBrowserTest.FilePac/1 +-SystemNetworkContext/NetworkContextConfigurationHttpPacBrowserTest.Http* +-SystemNetworkContext/NetworkContextConfigurationManagedProxySettingsBrowserTest.Max* +-SystemNetworkContext/NetworkContextConfigurationProxySettingsBrowserTest.MaxConnectionsPerProxy/0 +-TabCaptureApiTest.ActiveTabPermission +-TabCaptureApiTest.ApiTests +-TabCaptureApiTest.Constraints +-TabCaptureApiTest.FullscreenEvents +-TabCaptureApiTest.GrantForChromePages +-TabCaptureApiTest.TabIndicator +-TabGroupEditorBubbleViewDialogBrowserTest.InvokeUi_default +-TabHoverCardBubbleViewBrowserTest.InvokeUi_tab_hover_card +-TabHoverCardBubbleViewBrowserTest.Widget* +-TabRestoreTest.Restore* +-TabRestoreTest.TabsFromRestoredWindowsAreLoadedGradually +-TabSearchAppTest.All +-TabSearchButtonBrowserUITest.InvokeUi_default +-TabSearchItemTest.All +-TabSearchUIBrowserTest.Close* +-TabSearchUIBrowserTest.InitialTabItemsListed +-TabSearchUIBrowserTest.SwitchToTabAction +-TabStatsTrackerBrowserTest.TabStatsObserverBasics +-TabUsageScenarioTrackerBrowserTest.Full* +-TaskManagerBrowserTest.Dev* +-TaskManagerBrowserTest.HistoryNavigationInNewTab +-TaskManagerBrowserTest.IdleWakeups +-TaskManagerBrowserTest.JSHeapMemory +-TaskManagerBrowserTest.KillTab +-TaskManagerBrowserTest.NavigateAwayFromHungRenderer +-TaskManagerBrowserTest.Notice* +-TaskManagerBrowserTest.ShutdownWhileOpen +-TaskManagerBrowserTest.TotalSentDataObserved +-TaskManagerBrowserTest.WebWorkerJSHeapMemory +-TaskManagerViewTest.CloseByAccelerator +-TaskManagerViewTest.InitialSelection +-TaskManagerViewTest.RestoreBounds +-TaskManagerViewTest.TableStartsWithDefaultColumns +-ThemeServiceBrowserTest.ThemeDataPackInvalid +-ThirdPartyMetricsObserverBrowserTest.OneThirdPartyFrame_OneTimingRecorded +-ThirdPartyMetricsObserverBrowserTest.ThreeThirdPartyFrames_ThreeTimingsRecorded +-TipMarqueeViewBrowserTest.TipStartsExpanded +-TranslateBubbleViewBrowserTest.AlertAccessibleEvent +-TranslateBubbleViewBrowserTest.Close* +-TranslateBubbleVisualTest.InvokeUi_error +-TranslateManagerBrowserTest.Href* +-TrustSafetySentimentServiceBrowserTest.Page* +-UkmBrowserTest.ConsentAddedButNoSyncCheck +-UkmBrowserTest.HistoryDeleteCheck +-UkmBrowserTest.IncognitoPlusRegularCheck +-UkmBrowserTest.LogProtoData +-UkmBrowserTest.MetricsReportingCheck +-UkmBrowserTest.Multi* +-UkmBrowserTest.NetworkProviderPopulatesSystemProfile +-UkmBrowserTest.OpenNonSyncCheck +-UkmBrowserTest.Regular* +-UkmBrowserTest.ServiceListenerInitFailedCheck +-UkmBrowserTest.SingleDisableExtensionsSyncCheck +-UkmBrowserTestWithSyncTransport.NotEnabledForSecondaryAccountSync +-UkmConsentParamBrowserTests/UkmConsentParamBrowserTest.Group* +-UnloadTest.BrowserCloseTabWhenOtherTabHasListener +-UpdateRecommendedDialogTest.InvokeUi_default +-UpdateServiceTest.NoUpdate +-UpdateServiceTest.PolicyCorrupted +-UpdateServiceTest.SuccessfulUpdate +-UpdateServiceTest.TwoUpdateCheckErrors +-UpdateServiceTest.UninstallExtensionWhileUpdating +-UpdateServiceTest.UpdateCheckError +-UsbChooserBrowserTest.Invoke* +-UsbInternalsTest.WebUIValueRenderTest +-VariationsSafeModeEndToEndBrowserTest.ExtendedSafeModeEndToEnd +-VideoConferencingPictureInPictureWindowControllerBrowserTest.VideoConferencingActions +-ViewSourceTest.HttpPostInMainframe +-VirtualCardSelectionDialogBrowserTest.InvokeUi_OneCard +-WebAppBrowserTest.InScopePWAPopupsHaveCorrectSize +-WebAppBrowserTest.OffScopePWAPopupsHaveCorrectSize +-WebAppBrowserTest.PWASizeIsCorrectlyRestored +-WebAppDeclarativeLinkCapturingBrowserTest.InAppScopeNavigationIgnored +-WebAppFrameToolbarBrowserTest_WindowControlsOverlay.WindowControlsOverlayDraggableRegions +-WebAppIdentityUpdateConfirmationViewBrowserTest.CloseAppIdUpdateDialogOnUninstall +-WebAppIdentityUpdateConfirmationViewBrowserTest.InvokeUi_default +-WebAppIntegrationBrowserTest.ManifestUpdateScope +-WebAppIntegrationBrowserTest.VerifyWindowModeChanged +-WebAppIntegrationBrowserTest.Web* +-WebAppOpaqueBrowserFrameViewTest.Fullscreen +-WebAppPictureInPictureWindowControllerBrowserTest.Auto* +-WebAppProtocolHandlerIntentPickerDialogInteractiveBrowserTest.InvokeUi_CloseDialog +-WebAppUninstallDialogViewInteractiveBrowserTest.InvokeUi_ManualUninstall +-WebAudioBrowserTest.VerifyDynamicsCompressorFingerprint +-WebSocketBrowserHTTPConnectToTest.Web* +-WebSocketBrowserTest.FailuresReported +-WebSocketBrowserTest.ReuseMainPageBasicAuthCredentialsForWebSocket +-WebSocketBrowserTest.SSLConnectionLimit +-WebSocketBrowserTest.SecureWebSocketSplitRecords +-WebSocketBrowserTest.Send* +-WebSocketBrowserTest.Web* +-WebSocketBrowserTestWithAllowFileAccessFromFiles.CheckFileOrigin +-WebUiNtpInterceptionWebRequestAPITest.OneGoogleBarRequestsHidden +-WebViewAccessibilityTest.FocusAccessibility +-WebViewDPITest.Shim* +-WebViewScrollBubbling/WebViewGuestScrollTest.Scroll* +-WebViewScrollBubbling/WebViewGuestScrollTest.TestGuestWheelScrollsBubble/0 +-WebViewScrollBubbling/WebViewGuestScrollTouchTest.Test* +-WebViewSizeTest.AutoSize +-WebViewSizeTest.Shim* +-WebViewTest.AudibilityStatePropagates +-WebViewTest.AudioStateJavascriptAPI +-WebViewTest.Download* +-WebViewTest.Geolocation* +-WebViewTest.Interstitial* +-WebViewTest.NoPrerenderer +-WebViewTest.ReloadAfterCrash +-WebViewTest.Shim_TestRemoveWebviewOnExit +-WebViewTest.Task* +-WebViewTest.TouchpadPinchSyntheticWheelEvents +-WebViewWithZoomForDSFTest.Shim* +-WebauthnDialogBrowserTest.Invoke* +-WebstoreInstallerBrowserTest.WebstoreInstall +-WebstoreReinstallerBrowserTest.TestWebstoreReinstall +-WindowOpenApiTest.WindowOpenSized +-WorkProfileSigninConfirmationDialogTest.InvokeUi_default +-WorkerDevToolsTest.PauseInSharedWorkerInitialization +-ZoomBubbleBrowserTest.AnchorPositionsInFullscreen +-ZoomBubbleBrowserTest.BubbleSuppressingExtensionRefreshesExistingBubble +-ZoomBubbleDialogTest.InvokeUi_default +-ZoomControllerBrowserTest.RestoredPageScaleFromNavigation
diff --git a/testing/buildbot/internal.chromeos.fyi.json b/testing/buildbot/internal.chromeos.fyi.json index d6dfcca..6357e08 100644 --- a/testing/buildbot/internal.chromeos.fyi.json +++ b/testing/buildbot/internal.chromeos.fyi.json
@@ -1136,7 +1136,7 @@ { "args": [], "cros_board": "octopus", - "cros_img": "octopus-release/R99-14469.8.0", + "cros_img": "octopus-release/R100-14496.0.0", "name": "lacros_fyi_tast_tests_OCTOPUS_DEV", "swarming": {}, "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)", @@ -1158,7 +1158,7 @@ { "args": [], "cros_board": "octopus", - "cros_img": "octopus-release/R97-14324.80.0", + "cros_img": "octopus-release/R98-14388.52.0", "name": "lacros_fyi_tast_tests_OCTOPUS_STABLE", "swarming": {}, "tast_expr": "(\"group:mainline\" && \"dep:lacros\" && !informational)", @@ -1179,7 +1179,7 @@ { "args": [], "cros_board": "octopus", - "cros_img": "octopus-release/R99-14469.8.0", + "cros_img": "octopus-release/R100-14496.0.0", "name": "ozone_unittests_OCTOPUS_DEV", "swarming": {}, "test": "ozone_unittests", @@ -1199,7 +1199,7 @@ { "args": [], "cros_board": "octopus", - "cros_img": "octopus-release/R97-14324.80.0", + "cros_img": "octopus-release/R98-14388.52.0", "name": "ozone_unittests_OCTOPUS_STABLE", "swarming": {}, "test": "ozone_unittests",
diff --git a/testing/buildbot/test_suites.pyl b/testing/buildbot/test_suites.pyl index 805e724..2c438b9 100644 --- a/testing/buildbot/test_suites.pyl +++ b/testing/buildbot/test_suites.pyl
@@ -1756,6 +1756,16 @@ }, 'fuchsia_experimental_gtests': { + 'browser_tests': { + 'args': [ + '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.browser_tests.filter', + '--', + '--test-launcher-timeout=60000', + ], + 'swarming': { + 'shards': 40, + }, + }, 'content_browsertests': { 'args': [ '--test-launcher-filter-file=../../testing/buildbot/filters/fuchsia.content_browsertests.filter', @@ -6946,20 +6956,20 @@ 'ios_asan_tests': { 'ios_common_tests': { 'variants': [ - 'SIM_IPHONE_X_15_0', - 'SIM_IPAD_AIR_2_15_0', + 'SIM_IPHONE_X_15_2', + 'SIM_IPAD_AIR_2_15_2', ] }, 'ios_crash_unittests': { 'variants': [ - 'SIM_IPHONE_X_15_0', - 'SIM_IPAD_AIR_2_15_0', + 'SIM_IPHONE_X_15_2', + 'SIM_IPAD_AIR_2_15_2', ] }, 'ios_screen_size_dependent_tests': { 'variants': [ - 'SIM_IPHONE_X_15_0', - 'SIM_IPAD_AIR_2_15_0', + 'SIM_IPHONE_X_15_2', + 'SIM_IPAD_AIR_2_15_2', ] } }, @@ -6975,7 +6985,7 @@ 'ios_clang_tot_sim_tests': { 'ios_clang_tests': { 'variants': [ - 'SIM_IPHONE_6S_15_0', + 'SIM_IPHONE_6S_15_2', ] } }, @@ -6985,16 +6995,16 @@ 'ios_code_coverage_tests': { 'ios_common_tests': { 'variants': [ - 'SIM_IPHONE_6S_15_0', + 'SIM_IPHONE_6S_15_2', 'SIM_IPHONE_6S_14_4', ], }, 'ios_eg2_cq_tests': { 'mixins': ['xcode_parallelization'], 'variants': [ - 'SIM_IPHONE_6S_15_0', - 'SIM_IPHONE_7_15_0', - 'SIM_IPAD_AIR_2_15_0', + 'SIM_IPHONE_6S_15_2', + 'SIM_IPHONE_7_15_2', + 'SIM_IPAD_AIR_2_15_2', 'SIM_IPHONE_6S_14_4', 'SIM_IPHONE_7_14_4', 'SIM_IPAD_AIR_2_14_4', @@ -7003,9 +7013,9 @@ 'ios_eg2_tests': { 'mixins': ['xcode_parallelization'], 'variants': [ - 'SIM_IPHONE_7_15_0', - 'SIM_IPAD_AIR_2_15_0', - 'SIM_IPHONE_X_15_0', + 'SIM_IPHONE_7_15_2', + 'SIM_IPAD_AIR_2_15_2', + 'SIM_IPHONE_X_15_2', 'SIM_IPHONE_7_14_4', 'SIM_IPAD_AIR_2_14_4', 'SIM_IPHONE_X_14_4', @@ -7013,10 +7023,10 @@ }, 'ios_screen_size_dependent_tests': { 'variants': [ - 'SIM_IPHONE_6S_PLUS_15_0', - 'SIM_IPHONE_6S_15_0', - 'SIM_IPHONE_SE_1ST_GEN_15_0', - 'SIM_IPAD_AIR_2_15_0', + 'SIM_IPHONE_6S_PLUS_15_2', + 'SIM_IPHONE_6S_15_2', + 'SIM_IPHONE_SE_1ST_GEN_15_2', + 'SIM_IPAD_AIR_2_15_2', 'SIM_IPHONE_6S_PLUS_14_4', 'SIM_IPHONE_6S_14_4', 'SIM_IPHONE_SE_1ST_GEN_14_4', @@ -7028,7 +7038,7 @@ 'ios_simulator_cronet_tests': { 'ios_cronet_tests': { 'variants': [ - 'SIM_IPHONE_X_15_0', + 'SIM_IPHONE_X_15_2', ] } }, @@ -7038,9 +7048,9 @@ 'ios_eg2_tests': { 'mixins': ['xcode_parallelization'], 'variants': [ - 'SIM_IPHONE_7_15_0', - 'SIM_IPAD_AIR_2_15_0', - 'SIM_IPHONE_X_15_0', + 'SIM_IPHONE_7_15_2', + 'SIM_IPAD_AIR_2_15_2', + 'SIM_IPHONE_X_15_2', 'SIM_IPHONE_7_14_4', 'SIM_IPAD_AIR_2_14_4', 'SIM_IPHONE_X_14_4', @@ -7049,8 +7059,8 @@ 'ios_eg2_cq_tests': { 'mixins': ['xcode_parallelization'], 'variants': [ - 'SIM_IPHONE_7_15_0', - 'SIM_IPAD_AIR_2_15_0', + 'SIM_IPHONE_7_15_2', + 'SIM_IPAD_AIR_2_15_2', 'SIM_IPHONE_7_14_4', 'SIM_IPAD_AIR_2_14_4', ] @@ -7060,24 +7070,24 @@ 'ios_simulator_multi_window_tests': { 'ios_common_tests': { 'variants': [ - 'SIM_IPAD_AIR_2_15_0', + 'SIM_IPAD_AIR_2_15_2', ] }, 'ios_eg2_cq_tests': { 'mixins': ['xcode_parallelization'], 'variants': [ - 'SIM_IPAD_AIR_2_15_0', + 'SIM_IPAD_AIR_2_15_2', ] }, 'ios_eg2_tests': { 'mixins': ['xcode_parallelization'], 'variants': [ - 'SIM_IPAD_AIR_2_15_0', + 'SIM_IPAD_AIR_2_15_2', ] }, 'ios_screen_size_dependent_tests': { 'variants': [ - 'SIM_IPAD_AIR_2_15_0', + 'SIM_IPAD_AIR_2_15_2', ] } }, @@ -7106,7 +7116,7 @@ 'ios_crash_xcuitests': { 'mixins': ['xcode_parallelization'], 'variants': [ - 'SIM_IPHONE_7_15_0', + 'SIM_IPHONE_7_15_2', 'SIM_IPHONE_7_14_4', ] }, @@ -7117,22 +7127,22 @@ 'ios_common_tests': { 'variants': [ 'SIM_IPHONE_6S_14_4', - 'SIM_IPHONE_6S_15_0', + 'SIM_IPHONE_6S_15_2', ] }, 'ios_eg2_cq_tests': { 'mixins': ['xcode_parallelization'], 'variants': [ 'SIM_IPHONE_6S_14_4', - 'SIM_IPHONE_6S_15_0', + 'SIM_IPHONE_6S_15_2', ] }, 'ios_screen_size_dependent_tests': { 'variants': [ - 'SIM_IPHONE_6S_PLUS_15_0', - 'SIM_IPHONE_6S_15_0', - 'SIM_IPHONE_SE_1ST_GEN_15_0', - 'SIM_IPAD_AIR_2_15_0', + 'SIM_IPHONE_6S_PLUS_15_2', + 'SIM_IPHONE_6S_15_2', + 'SIM_IPHONE_SE_1ST_GEN_15_2', + 'SIM_IPAD_AIR_2_15_2', 'SIM_IPHONE_6S_PLUS_14_4', 'SIM_IPHONE_6S_14_4', 'SIM_IPHONE_SE_1ST_GEN_14_4',
diff --git a/testing/buildbot/variants.pyl b/testing/buildbot/variants.pyl index 0d49e7de..2a166a3d 100644 --- a/testing/buildbot/variants.pyl +++ b/testing/buildbot/variants.pyl
@@ -200,18 +200,6 @@ 'ios_runtime_cache_14_5', ], }, - 'SIM_IPHONE_6S_15_0': { - 'args': [ - '--platform', - 'iPhone 6s', - '--version', - '15.0' - ], - 'identifier': 'iPhone 6s 15.0', - 'mixins': [ - 'ios_runtime_cache_15_0', - ], - }, 'SIM_IPHONE_6S_15_2': { 'args': [ '--platform', @@ -248,18 +236,6 @@ 'ios_runtime_cache_14_5', ], }, - 'SIM_IPHONE_6S_PLUS_15_0': { - 'args': [ - '--platform', - 'iPhone 6s Plus', - '--version', - '15.0', - ], - 'identifier': 'iPhone 6s Plus 15.0', - 'mixins': [ - 'ios_runtime_cache_15_0', - ], - }, 'SIM_IPHONE_6S_PLUS_15_2': { 'args': [ '--platform', @@ -296,18 +272,6 @@ 'ios_runtime_cache_14_5', ], }, - 'SIM_IPHONE_7_15_0': { - 'args': [ - '--platform', - 'iPhone 7', - '--version', - '15.0' - ], - 'identifier': 'iPhone 7 15.0', - 'mixins': [ - 'ios_runtime_cache_15_0', - ], - }, 'SIM_IPHONE_7_15_2': { 'args': [ '--platform', @@ -344,18 +308,6 @@ 'ios_runtime_cache_14_5', ], }, - 'SIM_IPHONE_SE_1ST_GEN_15_0': { - 'args': [ - '--platform', - 'iPhone SE (1st generation)', - '--version', - '15.0', - ], - 'identifier': 'iPhone SE (1st generation) 15.0', - 'mixins': [ - 'ios_runtime_cache_15_0', - ], - }, 'SIM_IPHONE_SE_1ST_GEN_15_2': { 'args': [ '--platform', @@ -435,7 +387,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M99', - 'revision': 'version:99.0.4844.23', + 'revision': 'version:99.0.4844.24', } ], }, @@ -507,7 +459,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M99', - 'revision': 'version:99.0.4844.23', + 'revision': 'version:99.0.4844.24', } ], }, @@ -579,7 +531,7 @@ { 'cipd_package': 'chromium/testing/weblayer-x86', 'location': 'weblayer_instrumentation_test_M99', - 'revision': 'version:99.0.4844.23', + 'revision': 'version:99.0.4844.24', } ], }, @@ -644,8 +596,8 @@ 'CROS_ATLAS_DEV': { 'skylab': { 'cros_board': 'atlas', - 'cros_chrome_version': '99.0.4844.14', - 'cros_img': 'atlas-release/R99-14469.8.0', + 'cros_chrome_version': '100.0.4863.0', + 'cros_img': 'atlas-release/R100-14496.0.0', }, 'enabled': True, 'identifier': 'ATLAS_DEV', @@ -662,8 +614,8 @@ 'CROS_ATLAS_STABLE': { 'skylab': { 'cros_board': 'atlas', - 'cros_chrome_version': '97.0.4692.102', - 'cros_img': 'atlas-release/R97-14324.80.0', + 'cros_chrome_version': '98.0.4758.91', + 'cros_img': 'atlas-release/R98-14388.52.0', }, 'enabled': True, 'identifier': 'ATLAS_STABLE', @@ -680,8 +632,8 @@ 'CROS_EVE_DEV': { 'skylab': { 'cros_board': 'eve', - 'cros_chrome_version': '99.0.4844.14', - 'cros_img': 'eve-release/R99-14469.8.0', + 'cros_chrome_version': '100.0.4863.0', + 'cros_img': 'eve-release/R100-14496.0.0', }, 'enabled': True, 'identifier': 'EVE_DEV', @@ -698,8 +650,8 @@ 'CROS_EVE_STABLE': { 'skylab': { 'cros_board': 'eve', - 'cros_chrome_version': '97.0.4692.102', - 'cros_img': 'eve-release/R97-14324.80.0', + 'cros_chrome_version': '98.0.4758.91', + 'cros_img': 'eve-release/R98-14388.52.0', }, 'enabled': True, 'identifier': 'EVE_STABLE', @@ -734,8 +686,8 @@ 'CROS_OCTOPUS_DEV': { 'skylab': { 'cros_board': 'octopus', - 'cros_chrome_version': '99.0.4844.14', - 'cros_img': 'octopus-release/R99-14469.8.0', + 'cros_chrome_version': '100.0.4863.0', + 'cros_img': 'octopus-release/R100-14496.0.0', }, 'enabled': True, 'identifier': 'OCTOPUS_DEV', @@ -752,8 +704,8 @@ 'CROS_OCTOPUS_STABLE': { 'skylab': { 'cros_board': 'octopus', - 'cros_chrome_version': '97.0.4692.102', - 'cros_img': 'octopus-release/R97-14324.80.0', + 'cros_chrome_version': '98.0.4758.91', + 'cros_img': 'octopus-release/R98-14388.52.0', }, 'enabled': True, 'identifier': 'OCTOPUS_STABLE',
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index 5654764d..2c0a76dc 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1939,8 +1939,12 @@ "experiments": [ { "name": "Enabled", + "params": { + "CreateCompositorWorkerContext": "true" + }, "enable_features": [ "EarlyCodeCache", + "EarlyEstablishGpuChannel", "FontManagerEarlyInit", "NavigationThreadingOptimizations", "OptimizeLookalikeUrlNavigationThrottle", @@ -1962,8 +1966,12 @@ "experiments": [ { "name": "Enabled", + "params": { + "CreateCompositorWorkerContext": "true" + }, "enable_features": [ "EarlyCodeCache", + "EarlyEstablishGpuChannel", "NavigationThreadingOptimizations", "OptimizeLookalikeUrlNavigationThrottle", "URLLoaderSyncClient" @@ -2445,27 +2453,6 @@ ] } ], - "DesktopOmniboxBookmarkPaths": [ - { - "platforms": [ - "chromeos", - "chromeos_lacros", - "linux", - "mac", - "windows", - "android", - "ios" - ], - "experiments": [ - { - "name": "Disabled", - "disable_features": [ - "OmniboxBookmarkPaths" - ] - } - ] - } - ], "DesktopReadingListAddFromDialog": [ { "platforms": [ @@ -2878,31 +2865,6 @@ ] } ], - "EarlyEstablishGpuChannel": [ - { - "platforms": [ - "android", - "android_weblayer", - "android_webview", - "chromeos", - "chromeos_lacros", - "linux", - "mac", - "windows" - ], - "experiments": [ - { - "name": "Enabled", - "params": { - "CreateCompositorWorkerContext": "true" - }, - "enable_features": [ - "EarlyEstablishGpuChannel" - ] - } - ] - } - ], "EarlyHintsPreloadForNavigation": [ { "platforms": [ @@ -4029,21 +3991,6 @@ ] } ], - "MixedContentDownloadDialog": [ - { - "platforms": [ - "android" - ], - "experiments": [ - { - "name": "Enabled", - "enable_features": [ - "EnableMixedContentDownloadDialog" - ] - } - ] - } - ], "MojoInlineMessagePayloads": [ { "platforms": [ @@ -4237,14 +4184,17 @@ "params": { "EntitySuggestionsReduceLatencyDecoderTimeout": "405", "MaxZeroSuggestMatches": "10", + "OmniboxBookmarkPathsUiDynamicReplaceUrl": "true", "OmniboxMaxURLMatches": "7", "RichAutocompletionAutocompleteNonPrefixAll": "true", "RichAutocompletionAutocompleteTitles": "true", + "ShortBookmarkSuggestionsByTotalInputLengthThreshold": "3", "UIMaxAutocompleteMatches": "8" }, "enable_features": [ "OmniboxAggregateShortcuts", "OmniboxBlurWithEscape", + "OmniboxBookmarkPaths", "OmniboxClosePopupWithEscape", "OmniboxDocumentProviderAso", "OmniboxEntitySuggestionsReduceLatency", @@ -4254,11 +4204,10 @@ "OmniboxPreserveLongerShortcutsText", "OmniboxRemoveSuggestionsFromClipboard", "OmniboxRichAutocompletion", + "OmniboxShortBookmarkSuggestionsByTotalInputLength", "OmniboxUIExperimentMaxAutocompleteMatches" ], - "disable_features": [ - "OmniboxShortBookmarkSuggestionsByTotalInputLength" - ] + "disable_features": [] } ] },
diff --git a/third_party/blink/common/client_hints/enabled_client_hints.cc b/third_party/blink/common/client_hints/enabled_client_hints.cc index 30320cd..bd238963 100644 --- a/third_party/blink/common/client_hints/enabled_client_hints.cc +++ b/third_party/blink/common/client_hints/enabled_client_hints.cc
@@ -90,23 +90,24 @@ return false; } -bool IsUaReducedClientHintEnabled( +bool IsUserAgentOriginTrialEnabled( const GURL& url, const GURL* third_party_url, - const net::HttpResponseHeaders* response_headers) { + const net::HttpResponseHeaders* response_headers, + base::StringPiece feature_name) { blink::TrialTokenValidator validator; base::Time now = base::Time::Now(); if (third_party_url == nullptr) { - // It's not a third-party embed request, validate the UserAgentReduction OT + // It's not a third-party embed request, validate the feature_name OT // token as normal. - return validator.RequestEnablesFeature(url, response_headers, - "UserAgentReduction", now); + return validator.RequestEnablesFeature(url, response_headers, feature_name, + now); } // Validate the third-party OT token. bool enabled = false; // Iterate through all of the Origin-Trial headers and validate if any of - // them are valid third-party OT tokens for the UserAgentReduction trial. + // them are valid third-party OT tokens for the feature_name trial. if (validator.IsTrialPossibleOnOrigin(*third_party_url)) { url::Origin origin = url::Origin::Create(url); url::Origin third_party_origin = url::Origin::Create(*third_party_url); @@ -116,7 +117,7 @@ blink::TrialTokenResult result = validator.ValidateToken(token, origin, &third_party_origin, now); if (result.Status() == blink::OriginTrialTokenStatus::kSuccess) { - if (result.ParsedToken()->feature_name() == "UserAgentReduction") { + if (result.ParsedToken()->feature_name() == feature_name) { enabled = true; break; } @@ -146,8 +147,13 @@ const bool should_send) { bool enabled = should_send; if (enabled && type == WebClientHintsType::kUAReduced) { + enabled = IsUserAgentOriginTrialEnabled( + url, third_party_url, response_headers, "UserAgentReduction"); + } + if (enabled && type == WebClientHintsType::kFullUserAgent) { enabled = - IsUaReducedClientHintEnabled(url, third_party_url, response_headers); + IsUserAgentOriginTrialEnabled(url, third_party_url, response_headers, + "SendFullUserAgentAfterReduction"); } SetIsEnabled(type, enabled); }
diff --git a/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc b/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc index 61a6983..eb3401d 100644 --- a/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc +++ b/third_party/blink/common/client_hints/enabled_client_hints_unittest.cc
@@ -57,6 +57,19 @@ response_headers_->AddHeader(header, value); } + void VerifyClientHintEnabledWithOriginTrailToken( + const std::string& token, + const GURL* third_party_url, + const WebClientHintsType client_hint_type, + bool expected_client_hint_enabled) { + AddHeader("Origin-Trial", token); + EnabledClientHints hints; + hints.SetIsEnabled(GURL(kOriginUrl), third_party_url, response_headers(), + client_hint_type, true); + EXPECT_TRUE(hints.IsEnabled(client_hint_type) == + expected_client_hint_enabled); + } + private: class TestOriginTrialPolicy : public OriginTrialPolicy { public: @@ -124,11 +137,10 @@ "LC" "AiZXhwaXJ5IjogMjAwMDAwMDAwMH0="; - AddHeader("Origin-Trial", kValidOriginTrialToken); - EnabledClientHints hints; - hints.SetIsEnabled(GURL(kOriginUrl), /*third_party_url=*/nullptr, - response_headers(), WebClientHintsType::kUAReduced, true); - EXPECT_TRUE(hints.IsEnabled(WebClientHintsType::kUAReduced)); + VerifyClientHintEnabledWithOriginTrailToken( + kValidOriginTrialToken, + /*third_party_url=*/nullptr, WebClientHintsType::kUAReduced, + /*expected_client_hint_enabled=*/true); } TEST_F(EnabledClientHintsTest, @@ -142,11 +154,10 @@ "LC" "AiZXhwaXJ5IjogMjAwMDAwMDAwMH0="; - AddHeader("Origin-Trial", kInvalidOriginTrialToken); - EnabledClientHints hints; - hints.SetIsEnabled(GURL(kOriginUrl), /*third_party_url=*/nullptr, - response_headers(), WebClientHintsType::kUAReduced, true); - EXPECT_FALSE(hints.IsEnabled(WebClientHintsType::kUAReduced)); + VerifyClientHintEnabledWithOriginTrailToken( + kInvalidOriginTrialToken, + /*third_party_url=*/nullptr, WebClientHintsType::kUAReduced, + /*expected_client_hint_enabled=*/false); } TEST_F(EnabledClientHintsTest, @@ -164,12 +175,10 @@ "nR5IjogdHJ1ZSwgImZlYXR1cmUiOiAiVXNlckFnZW50UmVkdWN0aW9uIiwgImV4cGlyeSI6I" "DIwMDAwMDAwMDB9"; - AddHeader("Origin-Trial", kValidThirdPartyOriginTrialToken); - EnabledClientHints hints; const GURL third_party_url = GURL(kThirdPartyOriginUrl); - hints.SetIsEnabled(GURL(kOriginUrl), &third_party_url, response_headers(), - WebClientHintsType::kUAReduced, true); - EXPECT_TRUE(hints.IsEnabled(WebClientHintsType::kUAReduced)); + VerifyClientHintEnabledWithOriginTrailToken( + kValidThirdPartyOriginTrialToken, &third_party_url, + WebClientHintsType::kUAReduced, /*expected_client_hint_enabled=*/true); } TEST_F(EnabledClientHintsTest, @@ -189,12 +198,94 @@ "ZmVhdHVyZSI6ICJVc2VyQWdlbnRSZWR1Y3Rpb24iLCAiZXhwaXJ5IjogMjAwMDAwMDAwMH0" "="; - AddHeader("Origin-Trial", kValidOriginTrialTokenForThirdPartyUrl); - EnabledClientHints hints; const GURL third_party_url = GURL(kThirdPartyOriginUrl); - hints.SetIsEnabled(GURL(kOriginUrl), &third_party_url, response_headers(), - WebClientHintsType::kUAReduced, true); - EXPECT_FALSE(hints.IsEnabled(WebClientHintsType::kUAReduced)); + VerifyClientHintEnabledWithOriginTrailToken( + kValidOriginTrialTokenForThirdPartyUrl, &third_party_url, + WebClientHintsType::kUAReduced, /*expected_client_hint_enabled=*/false); +} + +TEST_F(EnabledClientHintsTest, + EnabledUADDrepcationClientHintWithValidOriginTrialToken) { + // Generated by running (in tools/origin_trials): + // generate_token.py https://127.0.0.1:44444 SendFullUserAgentAfterReduction + // --expire-timestamp=2000000000 + // + // The Origin Trial token expires in 2033. Generate a new token by then, or + // find a better way to re-generate a test trial token. + static constexpr char kValidOriginTrialToken[] = + "A6+Ti/9KuXTgmFzOQwkTuO8k0QFH8vUaxmv0CllAET1/" + "307KShF6fhskMuBqFUvqO7ViAkZ+" + "NSeJhQI0n5aLggsAAABpeyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAi" + "ZmVhdHVyZSI6ICJTZW5kRnVsbFVzZXJBZ2VudEFmdGVyUmVkdWN0aW9uIiwgImV4cGlyeSI6" + "IDIwMDAwMDAwMDB9"; + + VerifyClientHintEnabledWithOriginTrailToken( + kValidOriginTrialToken, + /*third_party_url=*/nullptr, WebClientHintsType::kFullUserAgent, + /*expected_client_hint_enabled=*/true); +} + +TEST_F(EnabledClientHintsTest, + EnabledUADDrepcationClientHintWithInvalidOriginTrialToken) { + // A slight corruption (changing a character) of a valid OT token. + static constexpr char kInvalidOriginTrialToken[] = + "A6+Ti/9KuXTgmFzOQwkTuO8k0QFH8vUaxmv0CllAET1/" + "307KShF6fhskMuBqFUvqO7ViAkZ+" + "NSeJhQI0n5aLggsAAABpeyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDQiLCAi" + "ZmVhdHVyZSI6ICTZW5kRnVsbFVzZXJBZ2VudEFmdGVyUmVkdWN0aW9uIiwgImV4cGlyeSI6" + "IDIwMDAwMDAwMDB9"; + + VerifyClientHintEnabledWithOriginTrailToken( + kInvalidOriginTrialToken, + /*third_party_url=*/nullptr, WebClientHintsType::kFullUserAgent, + /*expected_client_hint_enabled=*/false); +} + +TEST_F(EnabledClientHintsTest, + EnabledUADDrepcationClientHintWithValidThirdPartyOriginTrialToken) { + // Generated by running (in tools/origin_trials): + // generate_token.py https://127.0.0.1:44445 SendFullUserAgentAfterReduction + // --expire-timestamp=2000000000 --is-third-party + // + // The Origin Trial token expires in 2033. Generate a new token by then, or + // find a better way to re-generate a test trial token. + static constexpr char kValidThirdPartyOriginTrialToken[] = + "A0q1jQxOoBMkORITt4dborMF2TE0MVT71JbLomfT4tg8nKuEiRcDNTLVEfSffhxcwqMYEmXs" + "p4CXXypHENjrvwgAAAB/" + "eyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDUiLCAiaXNUaGlyZFBhcnR5Ijog" + "dHJ1ZSwgImZlYXR1cmUiOiAiU2VuZEZ1bGxVc2VyQWdlbnRBZnRlclJlZHVjdGlvbiIsICJl" + "eHBpcnkiOiAyMDAwMDAwMDAwfQ=="; + + const GURL third_party_url = GURL(kThirdPartyOriginUrl); + VerifyClientHintEnabledWithOriginTrailToken( + kValidThirdPartyOriginTrialToken, &third_party_url, + WebClientHintsType::kFullUserAgent, + /*expected_client_hint_enabled=*/true); +} + +TEST_F(EnabledClientHintsTest, + EnabledUADDrepcationClientHintThirdPartyWithValidOriginTrialToken) { + // Generated by running (in tools/origin_trials): + // generate_token.py https://127.0.0.1:44445 SendFullUserAgentAfterReduction + // --expire-timestamp=2000000000 + // + // We are using a valid first party OT token for the third-party URL, which + // should be rejected by the TrialTokenValidator for third-party contexts. + // + // The Origin Trial token expires in 2033. Generate a new token by then, or + // find a better way to re-generate a test trial token. + static constexpr char kValidOriginTrialTokenForThirdPartyUrl[] = + "A0kGFcySC9Pfb0ouX/" + "Ks2SYCmUEIkhU0aje4kHgLaCTgeOKoUaIwcrVSsiZgs3Im2vmPHwcaoqwzr/" + "d0YqDtzQQAAABpeyJvcmlnaW4iOiAiaHR0cHM6Ly8xMjcuMC4wLjE6NDQ0NDUiLCAiZmVhdH" + "VyZSI6ICJTZW5kRnVsbFVzZXJBZ2VudEFmdGVyUmVkdWN0aW9uIiwgImV4cGlyeSI6IDIwMD" + "AwMDAwMDB9"; + + const GURL third_party_url = GURL(kThirdPartyOriginUrl); + VerifyClientHintEnabledWithOriginTrailToken( + kValidOriginTrialTokenForThirdPartyUrl, &third_party_url, + WebClientHintsType::kFullUserAgent, + /*expected_client_hint_enabled=*/false); } TEST_F(EnabledClientHintsTest, GetEnabledHints) {
diff --git a/third_party/blink/public/mojom/worker/shared_worker_factory.mojom b/third_party/blink/public/mojom/worker/shared_worker_factory.mojom index 00804f1..b483691 100644 --- a/third_party/blink/public/mojom/worker/shared_worker_factory.mojom +++ b/third_party/blink/public/mojom/worker/shared_worker_factory.mojom
@@ -49,6 +49,7 @@ url.mojom.Origin constructor_origin, string user_agent, + string full_user_agent, string reduced_user_agent, UserAgentMetadata ua_metadata, bool pause_on_start,
diff --git a/third_party/blink/public/platform/media/web_encrypted_media_client_impl.h b/third_party/blink/public/platform/media/web_encrypted_media_client_impl.h index 7432fcf..3d7a38f 100644 --- a/third_party/blink/public/platform/media/web_encrypted_media_client_impl.h +++ b/third_party/blink/public/platform/media/web_encrypted_media_client_impl.h
@@ -18,6 +18,7 @@ namespace media { class CdmFactory; +class KeySystems; class MediaPermission; struct CdmConfig; } // namespace media @@ -53,6 +54,12 @@ // Each stat is only reported once per renderer frame per key system. class Reporter; + // Callback for media::KeySystems initialization. + void OnKeySystemsUpdated(); + + // Helper function to call `KeySystemConfigSelector::SelectConfig()`. + void SelectConfig(WebEncryptedMediaRequest request); + // Callback for `KeySystemConfigSelector::SelectConfig()`. // `accumulated_configuration` and `cdm_config` are non-null iff `status` is // `kSupported`. `cdm_config->key_system` is the same as the requested key @@ -71,8 +78,13 @@ // Reporter singletons. std::unordered_map<std::string, std::unique_ptr<Reporter>> reporters_; - media::CdmFactory* cdm_factory_; + media::CdmFactory* const cdm_factory_; + media::KeySystems* const key_systems_; KeySystemConfigSelector key_system_config_selector_; + + // Pending requests while waiting for KeySystems initialization. + std::vector<WebEncryptedMediaRequest> pending_requests_; + base::WeakPtrFactory<WebEncryptedMediaClientImpl> weak_factory_{this}; };
diff --git a/third_party/blink/public/platform/platform.h b/third_party/blink/public/platform/platform.h index 92c5487..d188491a 100644 --- a/third_party/blink/public/platform/platform.h +++ b/third_party/blink/public/platform/platform.h
@@ -301,8 +301,12 @@ WrapSharedURLLoaderFactory( scoped_refptr<network::SharedURLLoaderFactory> factory); - // Returns the User-Agent string. + // Returns the default User-Agent string, it can either full User-Agent string + // or reduced User-Agent string based on policy setting. virtual WebString UserAgent() { return WebString(); } + // Returns the full User-Agent string. + virtual WebString FullUserAgent() { return WebString(); } + // Returns the reduced User-Agent string. virtual WebString ReducedUserAgent() { return WebString(); } // Returns the User Agent metadata. This will replace `UserAgent()` if we
diff --git a/third_party/blink/public/web/web_frame.h b/third_party/blink/public/web/web_frame.h index af13ee9..d02e60aa 100644 --- a/third_party/blink/public/web/web_frame.h +++ b/third_party/blink/public/web/web_frame.h
@@ -31,7 +31,6 @@ #ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_FRAME_H_ #define THIRD_PARTY_BLINK_PUBLIC_WEB_WEB_FRAME_H_ -#include "cc/paint/paint_canvas.h" #include "third_party/blink/public/common/tokens/tokens.h" #include "third_party/blink/public/mojom/frame/tree_scope_type.mojom-shared.h" #include "third_party/blink/public/mojom/security_context/insecure_request_policy.mojom-shared.h"
diff --git a/third_party/blink/public/web/web_local_frame.h b/third_party/blink/public/web/web_local_frame.h index fed1e95..e716d8e 100644 --- a/third_party/blink/public/web/web_local_frame.h +++ b/third_party/blink/public/web/web_local_frame.h
@@ -53,6 +53,10 @@ #include "ui/gfx/range/range.h" #include "v8/include/v8-forward.h" +namespace cc { +class PaintCanvas; +} // namespace cc + namespace gfx { class Point; class PointF;
diff --git a/third_party/blink/public/web/web_shared_worker.h b/third_party/blink/public/web/web_shared_worker.h index a2ae501..48302ca 100644 --- a/third_party/blink/public/web/web_shared_worker.h +++ b/third_party/blink/public/web/web_shared_worker.h
@@ -75,6 +75,7 @@ const WebString& name, WebSecurityOrigin constructor_origin, const WebString& user_agent, + const WebString& full_user_agent, const WebString& reduced_user_agent, const UserAgentMetadata& ua_metadata, const WebVector<WebContentSecurityPolicy>& content_security_policies,
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 50b8dc4..be9a6d4 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
@@ -955,4 +955,23 @@ return ToMicrotaskQueue(ExecutionContext::From(script_state)); } +bool IsInParallelAlgorithmRunnable(ExecutionContext* execution_context, + ScriptState* script_state) { + if (!execution_context || execution_context->IsContextDestroyed()) + return false; + + // It's possible that execution_context is the one of the + // document tree (i.e. the execution context of the document + // that the receiver object currently belongs to) and + // script_state is the one of the receiver object's creation + // context (i.e. the script state of the V8 context in which + // the receiver object was created). So, check the both contexts. + // TODO(yukishiino): Find the necessary and sufficient conditions of the + // runnability. + if (!script_state->ContextIsValid()) + return false; + + return true; +} + } // namespace blink
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 9f0f459..d547a84 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
@@ -527,6 +527,15 @@ v8::MicrotaskQueue* ToMicrotaskQueue(ExecutionContext*); v8::MicrotaskQueue* ToMicrotaskQueue(ScriptState*); +// Helper finction used in the callback functions to validate context. +// Returns true if the given execution context and V8 context are capable to run +// an "in parallel" algorithm, otherwise returns false. What implements an "in +// parallel" algorithm should check the runnability before using the context. +// https://html.spec.whatwg.org/C/#in-parallel +CORE_EXPORT CORE_EXPORT bool IsInParallelAlgorithmRunnable( + ExecutionContext* execution_context, + ScriptState* script_state); + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_BINDINGS_CORE_V8_V8_BINDING_FOR_CORE_H_
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc b/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc index 75da99de..e3b45c0 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc +++ b/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.cc
@@ -61,6 +61,17 @@ return AttachStackProperty(isolate, dom_exception); } +v8::Local<v8::Value> V8ThrowDOMException::CreateOrDie( + v8::Isolate* isolate, + DOMExceptionCode exception_code, + const String& sanitized_message, + const String& unsanitized_message) { + v8::Local<v8::Value> v8_value = CreateOrEmpty( + isolate, exception_code, sanitized_message, unsanitized_message); + CHECK(!v8_value.IsEmpty()); + return v8_value; +} + v8::Local<v8::Value> V8ThrowDOMException::AttachStackProperty( v8::Isolate* isolate, DOMException* dom_exception) {
diff --git a/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h b/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h index 170deae..1278ecd 100644 --- a/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h +++ b/third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h
@@ -35,6 +35,13 @@ const String& sanitized_message, const String& unsanitized_message = String()); + // Same as CreateOrEmpty, but performs CHECK for exception to not be empty. + static v8::Local<v8::Value> CreateOrDie( + v8::Isolate*, + DOMExceptionCode, + const String& sanitized_message, + const String& unsanitized_message = String()); + // Attaches a stacktrace to an existing DOMException object. This should only // be used when initializing a subclass of DOMException. In other cases, uses // CreateOrEmpty().
diff --git a/third_party/blink/renderer/build/scripts/json5_generator_unittest.py b/third_party/blink/renderer/build/scripts/json5_generator_unittest.py index 7ae4c83..3dc5b1f 100644 --- a/third_party/blink/renderer/build/scripts/json5_generator_unittest.py +++ b/third_party/blink/renderer/build/scripts/json5_generator_unittest.py
@@ -75,9 +75,9 @@ path2 = os.path.join(tmp, 'file2.h') with open(path1, 'wb') as f: - f.write('File1') + f.write(b'File1') with open(path2, 'wb') as f: - f.write('File2') + f.write(b'File2') self.assertTrue(os.path.exists(path1)) self.assertTrue(os.path.exists(path2)) @@ -91,9 +91,9 @@ path2 = os.path.join(tmp, 'file2.h') with open(path1, 'wb') as f: - f.write('File1') + f.write(b'File1') with open(path2, 'wb') as f: - f.write('File2') + f.write(b'File2') self.assertTrue(os.path.exists(path1)) self.assertTrue(os.path.exists(path2)) @@ -105,7 +105,7 @@ with tmp_dir() as tmp: path1 = os.path.join(tmp, 'file1.h') with open(path1, 'wb') as f: - f.write('File1') + f.write(b'File1') self.assertTrue(os.path.exists(path1)) # Don't throw when trying to clean up something that doesn't exist. CleanupWriter(tmp, set(['file1.h', 'file2.h'])).cleanup_files(tmp)
diff --git a/third_party/blink/renderer/core/css/active_style_sheets.cc b/third_party/blink/renderer/core/css/active_style_sheets.cc index b2b05ae..ddc00a5 100644 --- a/third_party/blink/renderer/core/css/active_style_sheets.cc +++ b/third_party/blink/renderer/core/css/active_style_sheets.cc
@@ -154,12 +154,31 @@ return false; } +bool HasDynamicViewportDependentMediaQueries( + const ActiveStyleSheetVector& active_style_sheets) { + for (const auto& active_sheet : active_style_sheets) { + if (active_sheet.first->HasDynamicViewportDependentMediaQueries()) + return true; + StyleSheetContents* contents = active_sheet.first->Contents(); + if (!contents->HasRuleSet()) + continue; + if (contents->GetRuleSet() + .Features() + .HasDynamicViewportDependentMediaQueries()) { + return true; + } + } + return false; +} + } // namespace bool AffectedByMediaValueChange(const ActiveStyleSheetVector& active_sheets, MediaValueChange change) { if (change == MediaValueChange::kSize) return HasSizeDependentMediaQueries(active_sheets); + if (change == MediaValueChange::kDynamicViewport) + return HasDynamicViewportDependentMediaQueries(active_sheets); DCHECK(change == MediaValueChange::kOther); return HasMediaQueries(active_sheets);
diff --git a/third_party/blink/renderer/core/css/css_style_sheet.cc b/third_party/blink/renderer/core/css/css_style_sheet.cc index 7bdc44a7..4839249 100644 --- a/third_party/blink/renderer/core/css/css_style_sheet.cc +++ b/third_party/blink/renderer/core/css/css_style_sheet.cc
@@ -301,13 +301,20 @@ bool CSSStyleSheet::MatchesMediaQueries(const MediaQueryEvaluator& evaluator) { viewport_dependent_media_query_results_.clear(); device_dependent_media_query_results_.clear(); + media_query_unit_flags_ = 0; if (!media_queries_) return true; return evaluator.Eval( *media_queries_, MediaQueryEvaluator::Results{&viewport_dependent_media_query_results_, - &device_dependent_media_query_results_}); + &device_dependent_media_query_results_, + &media_query_unit_flags_}); +} + +bool CSSStyleSheet::HasDynamicViewportDependentMediaQueries() const { + return media_query_unit_flags_ & + MediaQueryExpValue::UnitFlags::kDynamicViewport; } unsigned CSSStyleSheet::length() const {
diff --git a/third_party/blink/renderer/core/css/css_style_sheet.h b/third_party/blink/renderer/core/css/css_style_sheet.h index d9f25d9..1f3b145 100644 --- a/third_party/blink/renderer/core/css/css_style_sheet.h +++ b/third_party/blink/renderer/core/css/css_style_sheet.h
@@ -135,6 +135,7 @@ return !viewport_dependent_media_query_results_.IsEmpty() || !device_dependent_media_query_results_.IsEmpty(); } + bool HasDynamicViewportDependentMediaQueries() const; const MediaQueryResultList& ViewportDependentMediaQueryResults() const { return viewport_dependent_media_query_results_; } @@ -269,6 +270,8 @@ scoped_refptr<MediaQuerySet> media_queries_; MediaQueryResultList viewport_dependent_media_query_results_; MediaQueryResultList device_dependent_media_query_results_; + // See MediaQueryExpValue::UnitFlags. + unsigned media_query_unit_flags_ = 0; Member<Node> owner_node_; Member<CSSRule> owner_rule_;
diff --git a/third_party/blink/renderer/core/css/media_query_exp.cc b/third_party/blink/renderer/core/css/media_query_exp.cc index de8e760..62b9ee8 100644 --- a/third_party/blink/renderer/core/css/media_query_exp.cc +++ b/third_party/blink/renderer/core/css/media_query_exp.cc
@@ -577,6 +577,13 @@ return UnitFlags::kFontRelative; case CSSPrimitiveValue::UnitType::kRems: return UnitFlags::kRootFontRelative; + case CSSPrimitiveValue::UnitType::kDynamicViewportWidth: + case CSSPrimitiveValue::UnitType::kDynamicViewportHeight: + case CSSPrimitiveValue::UnitType::kDynamicViewportInlineSize: + case CSSPrimitiveValue::UnitType::kDynamicViewportBlockSize: + case CSSPrimitiveValue::UnitType::kDynamicViewportMin: + case CSSPrimitiveValue::UnitType::kDynamicViewportMax: + return UnitFlags::kDynamicViewport; default: return UnitFlags::kNone; }
diff --git a/third_party/blink/renderer/core/css/media_query_exp.h b/third_party/blink/renderer/core/css/media_query_exp.h index 930e358..d985a16 100644 --- a/third_party/blink/renderer/core/css/media_query_exp.h +++ b/third_party/blink/renderer/core/css/media_query_exp.h
@@ -92,6 +92,7 @@ kNone = 0x0, kFontRelative = 0x1, kRootFontRelative = 0x2, + kDynamicViewport = 0x4, }; UnitFlags GetUnitFlags() const;
diff --git a/third_party/blink/renderer/core/css/media_query_exp_test.cc b/third_party/blink/renderer/core/css/media_query_exp_test.cc index 55abcb93..728dfb5 100644 --- a/third_party/blink/renderer/core/css/media_query_exp_test.cc +++ b/third_party/blink/renderer/core/css/media_query_exp_test.cc
@@ -30,6 +30,11 @@ return MediaQueryExpValue(value, CSSPrimitiveValue::UnitType::kRems); } +MediaQueryExpValue DvhValue(double value) { + return MediaQueryExpValue( + value, CSSPrimitiveValue::UnitType::kDynamicViewportHeight); +} + MediaQueryExpValue InvalidValue() { return MediaQueryExpValue(); } @@ -361,6 +366,9 @@ // 10rem < width EXPECT_EQ(MediaQueryExpValue::UnitFlags::kRootFontRelative, LeftExp("width", LtCmp(RemValue(10.0))).GetUnitFlags()); + // 10dvh < width + EXPECT_EQ(MediaQueryExpValue::UnitFlags::kDynamicViewport, + LeftExp("width", LtCmp(DvhValue(10.0))).GetUnitFlags()); } TEST(MediaQueryExpTest, UtilsNullptrHandling) {
diff --git a/third_party/blink/renderer/core/css/media_query_matcher.cc b/third_party/blink/renderer/core/css/media_query_matcher.cc index 7379575..8b03daf 100644 --- a/third_party/blink/renderer/core/css/media_query_matcher.cc +++ b/third_party/blink/renderer/core/css/media_query_matcher.cc
@@ -62,7 +62,7 @@ evaluator_ = CreateEvaluator(); if (evaluator_) - return evaluator_->Eval(*media); + return evaluator_->Eval(*media, {nullptr, nullptr, &unit_flags_}); return false; } @@ -135,6 +135,11 @@ document_->EnqueueMediaQueryChangeListeners(listeners_to_notify); } +void MediaQueryMatcher::DynamicViewportChanged() { + if (unit_flags_ & MediaQueryExpValue::UnitFlags::kDynamicViewport) + ViewportChanged(); +} + void MediaQueryMatcher::Trace(Visitor* visitor) const { visitor->Trace(document_); visitor->Trace(evaluator_);
diff --git a/third_party/blink/renderer/core/css/media_query_matcher.h b/third_party/blink/renderer/core/css/media_query_matcher.h index e950f63..3c58e9b 100644 --- a/third_party/blink/renderer/core/css/media_query_matcher.h +++ b/third_party/blink/renderer/core/css/media_query_matcher.h
@@ -60,6 +60,8 @@ void MediaFeaturesChanged(); void ViewportChanged(); + // Invokes ViewportChanged, if this matcher depends on the dynamic viewport. + void DynamicViewportChanged(); bool Evaluate(const MediaQuerySet*); void Trace(Visitor*) const; @@ -75,6 +77,14 @@ using ViewportListenerSet = HeapLinkedHashSet<Member<MediaQueryListListener>>; ViewportListenerSet viewport_listeners_; + + // The set of unit flags seen by Evaluate. + // + // We currently only act on kDynamicViewport. In the future we could also + // look at the other values to improve invalidation in those cases. + // + // See MediaQueryExpValue::UnitFlags. + unsigned unit_flags_ = 0; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/css/media_value_change.h b/third_party/blink/renderer/core/css/media_value_change.h index 4f161cc7..b87389bf 100644 --- a/third_party/blink/renderer/core/css/media_value_change.h +++ b/third_party/blink/renderer/core/css/media_value_change.h
@@ -10,6 +10,8 @@ enum class MediaValueChange { // Viewport or device size changed. width/height/device-width/device-height. kSize, + // dv* unit evaluation changed. + kDynamicViewport, // Any other value which affect media query evaluations changed. kOther, };
diff --git a/third_party/blink/renderer/core/css/rule_feature_set.cc b/third_party/blink/renderer/core/css/rule_feature_set.cc index ee435fe2..a5964bb 100644 --- a/third_party/blink/renderer/core/css/rule_feature_set.cc +++ b/third_party/blink/renderer/core/css/rule_feature_set.cc
@@ -1270,6 +1270,7 @@ type_rule_invalidation_set_ = nullptr; viewport_dependent_media_query_results_.clear(); device_dependent_media_query_results_.clear(); + media_query_unit_flags_ = 0; classes_in_has_argument_.clear(); attributes_in_has_argument_.clear(); ids_in_has_argument_.clear(); @@ -1278,6 +1279,11 @@ pseudos_in_has_argument_.clear(); } +bool RuleFeatureSet::HasDynamicViewportDependentMediaQueries() const { + return media_query_unit_flags_ & + MediaQueryExpValue::UnitFlags::kDynamicViewport; +} + void RuleFeatureSet::CollectInvalidationSetsForClass( InvalidationLists& invalidation_lists, Element& element,
diff --git a/third_party/blink/renderer/core/css/rule_feature_set.h b/third_party/blink/renderer/core/css/rule_feature_set.h index 35df8f4..77e62474 100644 --- a/third_party/blink/renderer/core/css/rule_feature_set.h +++ b/third_party/blink/renderer/core/css/rule_feature_set.h
@@ -104,10 +104,12 @@ MediaQueryResultList& DeviceDependentMediaQueryResults() { return device_dependent_media_query_results_; } + unsigned& MediaQueryUnitFlags() { return media_query_unit_flags_; } bool HasMediaQueryResults() const { return !viewport_dependent_media_query_results_.IsEmpty() || !device_dependent_media_query_results_.IsEmpty(); } + bool HasDynamicViewportDependentMediaQueries() const; // Collect descendant and sibling invalidation sets. void CollectInvalidationSetsForClass(InvalidationLists&, @@ -489,6 +491,7 @@ scoped_refptr<DescendantInvalidationSet> type_rule_invalidation_set_; MediaQueryResultList viewport_dependent_media_query_results_; MediaQueryResultList device_dependent_media_query_results_; + unsigned media_query_unit_flags_{0}; ValuesInHasArgument classes_in_has_argument_; ValuesInHasArgument attributes_in_has_argument_; ValuesInHasArgument ids_in_has_argument_;
diff --git a/third_party/blink/renderer/core/css/rule_set.cc b/third_party/blink/renderer/core/css/rule_set.cc index 5f1f41c..396f3229 100644 --- a/third_party/blink/renderer/core/css/rule_set.cc +++ b/third_party/blink/renderer/core/css/rule_set.cc
@@ -483,7 +483,8 @@ bool match_media = evaluator.Eval( *media_queries, MediaQueryEvaluator::Results{ &features_.ViewportDependentMediaQueryResults(), - &features_.DeviceDependentMediaQueryResults()}); + &features_.DeviceDependentMediaQueryResults(), + &features_.MediaQueryUnitFlags()}); media_query_set_results_.push_back( MediaQuerySetResult(*media_queries, match_media)); return match_media;
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc index 1fb8e7f..99be2c0 100644 --- a/third_party/blink/renderer/core/css/style_engine_test.cc +++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -25,6 +25,8 @@ #include "third_party/blink/renderer/core/css/css_style_sheet.h" #include "third_party/blink/renderer/core/css/css_test_helpers.h" #include "third_party/blink/renderer/core/css/media_query_list.h" +#include "third_party/blink/renderer/core/css/media_query_list_listener.h" +#include "third_party/blink/renderer/core/css/media_query_matcher.h" #include "third_party/blink/renderer/core/css/parser/css_parser_context.h" #include "third_party/blink/renderer/core/css/properties/css_property_ref.h" #include "third_party/blink/renderer/core/css/resolver/scoped_style_resolver.h" @@ -58,6 +60,7 @@ #include "third_party/blink/renderer/core/testing/color_scheme_helper.h" #include "third_party/blink/renderer/core/testing/core_unit_test_helper.h" #include "third_party/blink/renderer/core/testing/dummy_page_holder.h" +#include "third_party/blink/renderer/core/testing/page_test_base.h" #include "third_party/blink/renderer/core/testing/sim/sim_request.h" #include "third_party/blink/renderer/core/testing/sim/sim_test.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" @@ -70,13 +73,8 @@ namespace blink { -class StyleEngineTest : public testing::Test { +class StyleEngineTest : public PageTestBase { protected: - void SetUp() override; - - Document& GetDocument() { return dummy_page_holder_->GetDocument(); } - StyleEngine& GetStyleEngine() { return GetDocument().GetStyleEngine(); } - bool IsDocumentStyleSheetCollectionClean() { return !GetStyleEngine().ShouldUpdateDocumentStyleSheetCollection(); } @@ -143,8 +141,17 @@ return timeline->GetRule(); } - private: - std::unique_ptr<DummyPageHolder> dummy_page_holder_; + void SimulateFrame() { + auto new_time = GetAnimationClock().CurrentTime() + base::Milliseconds(100); + GetPage().Animator().ServiceScriptedAnimations(new_time); + } + + std::unique_ptr<DummyPageHolder> DummyPageHolderWithHTML(String html) { + auto holder = std::make_unique<DummyPageHolder>(gfx::Size(800, 600)); + holder->GetDocument().documentElement()->setInnerHTML(html); + holder->GetDocument().View()->UpdateAllLifecyclePhasesForTest(); + return holder; + } }; class StyleEngineContainerQueryTest : public StyleEngineTest, @@ -155,10 +162,6 @@ : ScopedCSSContainerQueriesForTest(true), ScopedLayoutNGForTest(true) {} }; -void StyleEngineTest::SetUp() { - dummy_page_holder_ = std::make_unique<DummyPageHolder>(gfx::Size(800, 600)); -} - StyleEngineTest::RuleSetInvalidation StyleEngineTest::ScheduleInvalidationsForRules(TreeScope& tree_scope, const String& css_text) { @@ -3633,6 +3636,113 @@ EXPECT_FALSE(target_dvh->NeedsStyleRecalc()); } +TEST_F(StyleEngineTest, DynamicViewportUnitsInMediaQuery) { + ScopedCSSViewportUnits4ForTest flag(true); + + // Changes in the dynamic viewport should not affect NeedsActiveStyleUpdate + // when we don't use dynamic viewport units. + { + auto holder = DummyPageHolderWithHTML(R"HTML( + <style> + @media (min-width: 50vh) { + :root { color: green; } + } + </style> + )HTML"); + Document& document = holder->GetDocument(); + + EXPECT_FALSE(document.GetStyleEngine().NeedsActiveStyleUpdate()); + document.DynamicViewportUnitsChanged(); + EXPECT_FALSE(document.GetStyleEngine().NeedsActiveStyleUpdate()); + } + + // NeedsActiveStyleUpdate should be set when dv* units are used. + { + auto holder = DummyPageHolderWithHTML(R"HTML( + <style> + @media (min-width: 50dvh) { + :root { color: green; } + } + </style> + )HTML"); + Document& document = holder->GetDocument(); + + EXPECT_FALSE(document.GetStyleEngine().NeedsActiveStyleUpdate()); + document.DynamicViewportUnitsChanged(); + EXPECT_TRUE(document.GetStyleEngine().NeedsActiveStyleUpdate()); + } + + // Same as the first test, but with media attribute. + { + auto holder = DummyPageHolderWithHTML(R"HTML( + <style media="(min-width: 50vh)"> + :root { color: green; } + </style> + )HTML"); + Document& document = holder->GetDocument(); + + EXPECT_FALSE(document.GetStyleEngine().NeedsActiveStyleUpdate()); + document.DynamicViewportUnitsChanged(); + EXPECT_FALSE(document.GetStyleEngine().NeedsActiveStyleUpdate()); + } + + // // Same as the second test, but with media attribute. + { + auto holder = DummyPageHolderWithHTML(R"HTML( + <style media="(min-width: 50dvh)"> + :root { color: green; } + </style> + )HTML"); + Document& document = holder->GetDocument(); + + EXPECT_FALSE(document.GetStyleEngine().NeedsActiveStyleUpdate()); + document.DynamicViewportUnitsChanged(); + EXPECT_TRUE(document.GetStyleEngine().NeedsActiveStyleUpdate()); + } +} + +namespace { + +class TestMediaQueryListListener : public MediaQueryListListener { + public: + void NotifyMediaQueryChanged() override { notified = true; } + bool notified = false; +}; + +} // namespace + +TEST_F(StyleEngineTest, DynamicViewportUnitsInMediaQueryMatcher) { + ScopedCSSViewportUnits4ForTest flag(true); + + auto& matcher = GetDocument().GetMediaQueryMatcher(); + auto* listener = MakeGarbageCollected<TestMediaQueryListListener>(); + matcher.AddViewportListener(listener); + + // Note: SimulateFrame is responsible for eventually causing dispatch of + // pending events to MediaQueryListListener. + // See step 10.8 (call to CallMediaQueryListListeners) in + // ScriptedAnimationController::ServiceScriptedAnimations. + + auto mq_static = MediaQuerySet::Create("(min-width: 50vh)", + GetDocument().GetExecutionContext()); + ASSERT_TRUE(mq_static); + matcher.Evaluate(mq_static.get()); + GetDocument().DynamicViewportUnitsChanged(); + SimulateFrame(); + EXPECT_FALSE(listener->notified); + + // Evaluating a media query with dv* units will mark the MediaQueryMatcher + // as dependent on such units, hence we should see events when calling + // DynamicViewportUnitsChanged after that. + auto mq_dynamic = MediaQuerySet::Create("(min-width: 50dvh)", + GetDocument().GetExecutionContext()); + ASSERT_TRUE(mq_dynamic); + matcher.Evaluate(mq_dynamic.get()); + GetDocument().DynamicViewportUnitsChanged(); + SimulateFrame(); + EXPECT_TRUE(listener->notified); +} + class StyleEngineSimTest : public SimTest {}; TEST_F(StyleEngineSimTest, OwnerColorScheme) {
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index bfe56f94..dae6f51c 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -4584,11 +4584,9 @@ void Document::DynamicViewportUnitsChanged() { if (!RuntimeEnabledFeatures::CSSViewportUnits4Enabled()) return; - // TODO(crbug.com/1093055): Avoid invalidating media queries if dv* is not - // used. - MediaQueryAffectingValueChanged(MediaValueChange::kSize); + MediaQueryAffectingValueChanged(MediaValueChange::kDynamicViewport); if (media_query_matcher_) - media_query_matcher_->ViewportChanged(); + media_query_matcher_->DynamicViewportChanged(); if (!HasDynamicViewportUnits()) return; GetStyleResolver().SetResizedForViewportUnits();
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc index 86bbee5..977c44a 100644 --- a/third_party/blink/renderer/core/dom/node.cc +++ b/third_party/blink/renderer/core/dom/node.cc
@@ -772,8 +772,7 @@ static Node* FindViablePreviousSibling( const Node& node, - const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes -) { + const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes) { for (Node* sibling = node.previousSibling(); sibling; sibling = sibling->previousSibling()) { if (!IsNodeInNodes(sibling, nodes)) @@ -784,8 +783,7 @@ static Node* FindViableNextSibling( const Node& node, - const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes -) { + const HeapVector<Member<V8UnionNodeOrStringOrTrustedScript>>& nodes) { for (Node* sibling = node.nextSibling(); sibling; sibling = sibling->nextSibling()) { if (!IsNodeInNodes(sibling, nodes)) @@ -1365,11 +1363,10 @@ if (change_type > existing_change_type) SetStyleChange(change_type); - auto* this_element = DynamicTo<Element>(this); if (existing_change_type == kNoStyleChange) MarkAncestorsWithChildNeedsStyleRecalc(); - if (this_element && HasRareData()) + if (auto* this_element = DynamicTo<Element>(this)) this_element->SetAnimationStyleChange(false); if (auto* svg_element = DynamicTo<SVGElement>(this))
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 738ea70..ad6a3add 100644 --- a/third_party/blink/renderer/core/execution_context/execution_context.cc +++ b/third_party/blink/renderer/core/execution_context/execution_context.cc
@@ -47,6 +47,7 @@ #include "third_party/blink/renderer/core/frame/local_dom_window.h" #include "third_party/blink/renderer/core/frame/web_feature.h" #include "third_party/blink/renderer/core/inspector/console_message.h" +#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h" #include "third_party/blink/renderer/core/loader/document_loader.h" #include "third_party/blink/renderer/core/origin_trials/origin_trial_context.h" #include "third_party/blink/renderer/core/workers/worker_global_scope.h"
diff --git a/third_party/blink/renderer/core/execution_context/navigator_base.cc b/third_party/blink/renderer/core/execution_context/navigator_base.cc index 0961d0f..24293de6 100644 --- a/third_party/blink/renderer/core/execution_context/navigator_base.cc +++ b/third_party/blink/renderer/core/execution_context/navigator_base.cc
@@ -36,6 +36,13 @@ if (execution_context) execution_context->ReportNavigatorUserAgentAccess(); + // If the User-Agent string is opted into the SendFullUserAgentAfterReduction, + // platform should be a full value. + if (RuntimeEnabledFeatures::SendFullUserAgentAfterReductionEnabled( + execution_context)) { + return NavigatorID::platform(); + } + // If the User-Agent string is frozen, platform should be a value // matching the frozen string per https://github.com/WICG/ua-client-hints. // See content::frozen_user_agent_strings.
diff --git a/third_party/blink/renderer/core/execution_context/navigator_base.h b/third_party/blink/renderer/core/execution_context/navigator_base.h index 01c6713..724d3ff7 100644 --- a/third_party/blink/renderer/core/execution_context/navigator_base.h +++ b/third_party/blink/renderer/core/execution_context/navigator_base.h
@@ -27,7 +27,6 @@ #include "third_party/blink/renderer/core/frame/navigator_language.h" #include "third_party/blink/renderer/core/frame/navigator_on_line.h" #include "third_party/blink/renderer/core/frame/navigator_ua.h" -#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/heap/garbage_collected.h" #include "third_party/blink/renderer/platform/supplementable.h"
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 09c9980..adb307a 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
@@ -197,6 +197,7 @@ const WebString& name, WebSecurityOrigin constructor_origin, const WebString& user_agent, + const WebString& full_user_agent, const WebString& reduced_user_agent, const UserAgentMetadata& ua_metadata, const WebVector<WebContentSecurityPolicy>& content_security_policies, @@ -251,6 +252,7 @@ GenericFontFamilySettings()); bool reduced_ua_enabled = false; + bool full_ua_enabled = false; if (worker_main_script_load_params && worker_main_script_load_params->response_head && worker_main_script_load_params->response_head->headers) { @@ -258,6 +260,10 @@ blink::WebStringToGURL(script_request_url.GetString()), worker_main_script_load_params->response_head->headers.get(), "UserAgentReduction", base::Time::Now()); + full_ua_enabled = blink::TrialTokenValidator().RequestEnablesFeature( + blink::WebStringToGURL(script_request_url.GetString()), + worker_main_script_load_params->response_head->headers.get(), + "SendFullUserAgentAfterReduction", base::Time::Now()); } // Some params (e.g. address space) passed to GlobalScopeCreationParams are @@ -265,8 +271,9 @@ // thread. auto creation_params = std::make_unique<GlobalScopeCreationParams>( script_request_url, script_type, name, - reduced_ua_enabled ? reduced_user_agent : user_agent, ua_metadata, - std::move(web_worker_fetch_context), + full_ua_enabled ? full_user_agent + : (reduced_ua_enabled ? reduced_user_agent : user_agent), + ua_metadata, std::move(web_worker_fetch_context), ConvertToMojoBlink(content_security_policies), Vector<network::mojom::blink::ContentSecurityPolicyPtr>(), outside_settings_object->GetReferrerPolicy(), @@ -346,6 +353,7 @@ const WebString& name, WebSecurityOrigin constructor_origin, const WebString& user_agent, + const WebString& full_user_agent, const WebString& reduced_user_agent, const UserAgentMetadata& ua_metadata, const WebVector<WebContentSecurityPolicy>& content_security_policies, @@ -367,8 +375,8 @@ base::WrapUnique(new WebSharedWorkerImpl(token, std::move(host), client)); worker->StartWorkerContext( script_request_url, script_type, credentials_mode, name, - constructor_origin, user_agent, reduced_user_agent, ua_metadata, - content_security_policies, creation_address_space, + constructor_origin, user_agent, full_user_agent, reduced_user_agent, + ua_metadata, content_security_policies, creation_address_space, outside_fetch_client_settings_object, devtools_worker_token, std::move(content_settings), std::move(browser_interface_broker), pause_worker_context_on_start, std::move(worker_main_script_load_params),
diff --git a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h index 2c09ce2c..afc68c5 100644 --- a/third_party/blink/renderer/core/exported/web_shared_worker_impl.h +++ b/third_party/blink/renderer/core/exported/web_shared_worker_impl.h
@@ -102,6 +102,7 @@ const WebString& name, WebSecurityOrigin constructor_origin, const WebString& user_agent, + const WebString& full_user_agent, const WebString& reduced_user_agent, const blink::UserAgentMetadata& ua_metadata, const WebVector<WebContentSecurityPolicy>& content_security_policies,
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 0ea29bb..6265696 100644 --- a/third_party/blink/renderer/core/exported/web_view_test.cc +++ b/third_party/blink/renderer/core/exported/web_view_test.cc
@@ -5175,11 +5175,6 @@ TransformationMatrix expected_matrix; expected_matrix.MakeIdentity(); EXPECT_EQ(expected_matrix, web_view_impl->GetDeviceEmulationTransform()); - { - gfx::Rect visible_rect(1, 2, 3, 4); - dev_tools_emulator->OverrideVisibleRect(gfx::Size(), &visible_rect); - EXPECT_EQ(gfx::Rect(1, 2, 3, 4), visible_rect); // Was modified. - } // Override applies transform, sets visible rect, and disables // visual viewport clipping. @@ -5187,33 +5182,18 @@ dev_tools_emulator->ForceViewportForTesting(gfx::PointF(50, 55), 2.f); expected_matrix.MakeIdentity().Scale(2.f).Translate(-50, -55); EXPECT_EQ(expected_matrix, matrix); - { - gfx::Rect visible_rect(1, 2, 3, 4); - dev_tools_emulator->OverrideVisibleRect(gfx::Size(100, 150), &visible_rect); - EXPECT_EQ(gfx::Rect(50, 55, 100, 150), visible_rect); - } // Setting new override discards previous one. matrix = dev_tools_emulator->ForceViewportForTesting(gfx::PointF(5.4f, 10.5f), 1.5f); expected_matrix.MakeIdentity().Scale(1.5f).Translate(-5.4f, -10.5f); EXPECT_EQ(expected_matrix, matrix); - { - gfx::Rect visible_rect(1, 2, 3, 4); - dev_tools_emulator->OverrideVisibleRect(gfx::Size(100, 150), &visible_rect); - EXPECT_EQ(gfx::Rect(5, 10, 101, 151), visible_rect); // Was modified. - } // Clearing override restores original transform, visible rect and // visual viewport clipping. matrix = dev_tools_emulator->ResetViewportForTesting(); expected_matrix.MakeIdentity(); EXPECT_EQ(expected_matrix, matrix); - { - gfx::Rect visible_rect(1, 2, 3, 4); - dev_tools_emulator->OverrideVisibleRect(gfx::Size(), &visible_rect); - EXPECT_EQ(gfx::Rect(1, 2, 3, 4), visible_rect); // Not modified. - } } TEST_F(WebViewTest, ViewportOverrideIntegratesDeviceMetricsOffsetAndScale) { @@ -5248,7 +5228,6 @@ SetViewportSize(gfx::Size(100, 150)); LocalFrameView* frame_view = web_view_impl->MainFrameImpl()->GetFrame()->View(); - DevToolsEmulator* dev_tools_emulator = web_view_impl->GetDevToolsEmulator(); TransformationMatrix expected_matrix; expected_matrix.MakeIdentity(); @@ -5271,12 +5250,6 @@ .Translate(100, 150) .Scale(1. / 1.5f); EXPECT_EQ(expected_matrix, web_view_impl->GetDeviceEmulationTransform()); - // Scale is irrelevant for visible rect. - { - gfx::Rect visible_rect(1, 2, 3, 4); - dev_tools_emulator->OverrideVisibleRect(gfx::Size(100, 150), &visible_rect); - EXPECT_EQ(gfx::Rect(50 - 100, 55 - 150, 100, 150), visible_rect); - } // Transform adapts to scroll changes. frame_view->LayoutViewport()->SetScrollOffset( @@ -5288,12 +5261,6 @@ .Translate(50, 55) .Scale(1. / 1.5f); EXPECT_EQ(expected_matrix, web_view_impl->GetDeviceEmulationTransform()); - // Visible rect adapts to scroll change. - { - gfx::Rect visible_rect(1, 2, 3, 4); - dev_tools_emulator->OverrideVisibleRect(gfx::Size(100, 150), &visible_rect); - EXPECT_EQ(gfx::Rect(50 - 50, 55 - 55, 100, 150), visible_rect); - } // Transform adapts to page scale changes. web_view_impl->SetPageScaleFactor(2.f); @@ -5303,12 +5270,6 @@ .Translate(50, 55) .Scale(1. / 2.f); EXPECT_EQ(expected_matrix, web_view_impl->GetDeviceEmulationTransform()); - // Visible rect doesn't change. - { - gfx::Rect visible_rect(1, 2, 3, 4); - dev_tools_emulator->OverrideVisibleRect(gfx::Size(100, 150), &visible_rect); - EXPECT_EQ(gfx::Rect(50 - 50, 55 - 55, 100, 150), visible_rect); - } } TEST_F(WebViewTest, ResizeForPrintingViewportUnits) {
diff --git a/third_party/blink/renderer/core/fetch/body_stream_buffer.cc b/third_party/blink/renderer/core/fetch/body_stream_buffer.cc index 98ae348..bdcfece 100644 --- a/third_party/blink/renderer/core/fetch/body_stream_buffer.cc +++ b/third_party/blink/renderer/core/fetch/body_stream_buffer.cc
@@ -227,6 +227,7 @@ FetchDataLoader::Client* client, ExceptionState& exception_state) { DCHECK(!loader_); + DCHECK(!keep_alive_); DCHECK(script_state_->ContextIsValid()); if (signal_) { if (signal_->aborted()) { @@ -240,6 +241,7 @@ auto* handle = ReleaseHandle(exception_state); if (exception_state.HadException()) return; + keep_alive_ = this; loader->Start(handle, MakeGarbageCollected<LoaderClient>( ExecutionContext::From(script_state_), this, client)); @@ -338,13 +340,10 @@ ProcessData(); } -bool BodyStreamBuffer::HasPendingActivity() const { - return loader_; -} - void BodyStreamBuffer::ContextDestroyed() { CancelConsumer(); UnderlyingSourceBase::ContextDestroyed(); + keep_alive_.Clear(); } bool BodyStreamBuffer::IsStreamReadable() const { @@ -499,14 +498,17 @@ void BodyStreamBuffer::EndLoading() { DCHECK(loader_); + keep_alive_.Clear(); loader_ = nullptr; } void BodyStreamBuffer::StopLoading() { - if (!loader_) + if (!loader_) { + DCHECK(!keep_alive_); return; + } loader_->Cancel(); - loader_ = nullptr; + EndLoading(); } BytesConsumer* BodyStreamBuffer::ReleaseHandle(
diff --git a/third_party/blink/renderer/core/fetch/body_stream_buffer.h b/third_party/blink/renderer/core/fetch/body_stream_buffer.h index 68b32c8..83d6377 100644 --- a/third_party/blink/renderer/core/fetch/body_stream_buffer.h +++ b/third_party/blink/renderer/core/fetch/body_stream_buffer.h
@@ -70,6 +70,9 @@ void DrainAsChunkedDataPipeGetter( ScriptState*, mojo::PendingReceiver<network::mojom::blink::ChunkedDataPipeGetter>); + // While loading is in progress, a SelfKeepAlive is used to prevent this + // object from being garbage collected. If the context is destroyed, the + // SelfKeepAlive is cleared. See https://crbug.com/1292744 for details. void StartLoading(FetchDataLoader*, FetchDataLoader::Client* /* client */, ExceptionState&); @@ -78,7 +81,6 @@ // UnderlyingSourceBase ScriptPromise pull(ScriptState*) override; ScriptPromise Cancel(ScriptState*, ScriptValue reason) override; - bool HasPendingActivity() const override; void ContextDestroyed() override; // BytesConsumer::Client @@ -159,6 +161,9 @@ // TODO(ricea): Remove remaining uses of |stream_broken_|. bool stream_broken_ = false; + + // Used to remain alive when there's a loader_. + SelfKeepAlive<BodyStreamBuffer> keep_alive_; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc b/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc index fdba0507..a22de9f 100644 --- a/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc +++ b/third_party/blink/renderer/core/fetch/body_stream_buffer_test.cc
@@ -139,7 +139,6 @@ EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(nullptr, buffer->GetSideDataBlobForTest()); EXPECT_EQ(side_data_blob, new1->GetSideDataBlobForTest()); @@ -213,13 +212,11 @@ // test, the stream will get disturbed when the microtask is performed. // TODO(yhirano): A uniformed behavior is preferred. EXPECT_FALSE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); v8::MicrotasksScope::PerformCheckpoint(scope.GetScriptState()->GetIsolate()); EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); new1->StartLoading(FetchDataLoader::CreateLoaderAsString( TextResourceDecoderOptions::CreateUTF8Decode()), @@ -249,7 +246,6 @@ EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest()); scoped_refptr<BlobDataHandle> output_blob_data_handle = buffer->DrainAsBlobDataHandle( @@ -257,7 +253,6 @@ EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(nullptr, buffer->GetSideDataBlobForTest()); EXPECT_EQ(blob_data_handle, output_blob_data_handle); } @@ -275,7 +270,6 @@ EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest()); EXPECT_FALSE(buffer->DrainAsBlobDataHandle( @@ -283,7 +277,6 @@ EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest()); } @@ -297,7 +290,6 @@ BodyStreamBuffer* buffer = MakeGarbageCollected<BodyStreamBuffer>( scope.GetScriptState(), stream, /*cached_metadata_handler=*/nullptr); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); EXPECT_TRUE(buffer->IsStreamReadable()); @@ -305,7 +297,6 @@ EXPECT_FALSE(buffer->DrainAsBlobDataHandle( BytesConsumer::BlobSizePolicy::kAllowBlobWithInvalidSize)); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); EXPECT_TRUE(buffer->IsStreamReadable()); @@ -329,13 +320,11 @@ EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest()); scoped_refptr<EncodedFormData> output_form_data = buffer->DrainAsFormData(); EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(nullptr, buffer->GetSideDataBlobForTest()); EXPECT_EQ(output_form_data->FlattenToString(), input_form_data->FlattenToString()); @@ -354,14 +343,12 @@ EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest()); EXPECT_FALSE(buffer->DrainAsFormData()); EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(side_data_blob, buffer->GetSideDataBlobForTest()); } @@ -374,14 +361,12 @@ BodyStreamBuffer* buffer = MakeGarbageCollected<BodyStreamBuffer>( scope.GetScriptState(), stream, /*cached_metadata_handler=*/nullptr); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); EXPECT_TRUE(buffer->IsStreamReadable()); EXPECT_FALSE(buffer->DrainAsFormData()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); EXPECT_TRUE(buffer->IsStreamReadable()); @@ -416,7 +401,6 @@ EXPECT_EQ(nullptr, buffer->GetSideDataBlobForTest()); EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_TRUE(buffer->HasPendingActivity()); checkpoint.Call(1); test::RunPendingTasks(); @@ -424,7 +408,6 @@ EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); ASSERT_TRUE(array_buffer); EXPECT_EQ("hello", String(static_cast<const char*>(array_buffer->Data()), array_buffer->ByteLength())); @@ -483,7 +466,6 @@ EXPECT_EQ(nullptr, buffer->GetSideDataBlobForTest()); EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_TRUE(buffer->HasPendingActivity()); checkpoint.Call(1); fake_task_runner_->RunUntilIdle(); @@ -492,7 +474,6 @@ EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(5u, blob_data_handle->size()); } @@ -524,7 +505,6 @@ EXPECT_EQ(nullptr, buffer->GetSideDataBlobForTest()); EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_TRUE(buffer->HasPendingActivity()); checkpoint.Call(1); test::RunPendingTasks(); @@ -532,7 +512,6 @@ EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); } TEST_F(BodyStreamBufferTest, LoadClosedHandle) { @@ -555,7 +534,6 @@ EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(nullptr, buffer->GetSideDataBlobForTest()); checkpoint.Call(1); @@ -566,7 +544,6 @@ EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); } TEST_F(BodyStreamBufferTest, LoadErroredHandle) { @@ -590,7 +567,6 @@ EXPECT_FALSE(buffer->IsStreamLocked()); EXPECT_FALSE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); EXPECT_EQ(nullptr, buffer->GetSideDataBlobForTest()); checkpoint.Call(1); @@ -601,7 +577,6 @@ EXPECT_TRUE(buffer->IsStreamLocked()); EXPECT_TRUE(buffer->IsStreamDisturbed()); - EXPECT_FALSE(buffer->HasPendingActivity()); } TEST_F(BodyStreamBufferTest, LoaderShouldBeKeptAliveByBodyStreamBuffer) { @@ -891,6 +866,42 @@ EXPECT_EQ(nullptr, buffer->TakeSideDataBlob()); } +TEST_F(BodyStreamBufferTest, KeptAliveWhileLoading) { + V8TestingScope scope; + auto* isolate = scope.GetIsolate(); + + WeakPersistent<BodyStreamBuffer> buffer; + WeakPersistent<ReplayingBytesConsumer> src; + { + v8::HandleScope handle_scope(isolate); + auto* client = MakeGarbageCollected<MockFetchDataLoaderClient>(); + + src = MakeGarbageCollected<ReplayingBytesConsumer>( + scope.GetDocument().GetTaskRunner(TaskType::kNetworking)); + src->Add(Command(Command::kWait)); + src->Add(Command(Command::kData, "hello")); + + buffer = BodyStreamBuffer::Create(scope.GetScriptState(), src, + /*signal=*/nullptr, + /*cached_metadata_handler=*/nullptr); + buffer->StartLoading(FetchDataLoader::CreateLoaderAsArrayBuffer(), client, + ASSERT_NO_EXCEPTION); + } + test::RunPendingTasks(); + + // The BodyStreamBuffer is kept alive while loading due to a SelfKeepAlive. + ThreadState::Current()->CollectAllGarbageForTesting(); + EXPECT_NE(nullptr, buffer); + + // Allow it to finish which clears the SelfKeepAlive and makes it collectable. + src->Add(Command(Command::kDone)); + src->TriggerOnStateChange(); + test::RunPendingTasks(); + + ThreadState::Current()->CollectAllGarbageForTesting(); + EXPECT_EQ(nullptr, buffer); +} + } // namespace } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc b/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc index 93718aa..931fef06 100644 --- a/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc +++ b/third_party/blink/renderer/core/frame/csp/execution_context_csp_delegate.cc
@@ -20,6 +20,7 @@ #include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/core/frame/report.h" #include "third_party/blink/renderer/core/frame/reporting_context.h" +#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h" #include "third_party/blink/renderer/core/loader/document_loader.h" #include "third_party/blink/renderer/core/loader/ping_loader.h" #include "third_party/blink/renderer/core/probe/core_probes.h"
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc index c5a05cb..889101d 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -372,6 +372,10 @@ if (!GetFrame()) return String(); + if (RuntimeEnabledFeatures::SendFullUserAgentAfterReductionEnabled(this)) { + return GetFrame()->Loader().FullUserAgent(); + } + if (RuntimeEnabledFeatures::UserAgentReductionEnabled(this)) return GetFrame()->Loader().ReducedUserAgent(); else
diff --git a/third_party/blink/renderer/core/frame/local_dom_window_test.cc b/third_party/blink/renderer/core/frame/local_dom_window_test.cc index f5799c6..bcf3922 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window_test.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window_test.cc
@@ -230,7 +230,7 @@ } } -TEST_F(LocalDOMWindowTest, ReducedUserAgent) { +TEST_F(LocalDOMWindowTest, UserAgent) { EXPECT_EQ(GetFrame().DomWindow()->UserAgent(), GetFrame().Loader().UserAgent()); { @@ -238,6 +238,11 @@ EXPECT_EQ(GetFrame().DomWindow()->UserAgent(), GetFrame().Loader().ReducedUserAgent()); } + { + ScopedSendFullUserAgentAfterReductionForTest s1(true); + EXPECT_EQ(GetFrame().DomWindow()->UserAgent(), + GetFrame().Loader().FullUserAgent()); + } } // Tests ExecutionContext::GetContentSecurityPolicyForCurrentWorld().
diff --git a/third_party/blink/renderer/core/frame/local_frame_client.h b/third_party/blink/renderer/core/frame/local_frame_client.h index cf6f792..45d397a7 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client.h +++ b/third_party/blink/renderer/core/frame/local_frame_client.h
@@ -248,6 +248,7 @@ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data) = 0; virtual String UserAgent() = 0; + virtual String FullUserAgent() = 0; virtual String ReducedUserAgent() = 0; virtual absl::optional<blink::UserAgentMetadata> UserAgentMetadata() = 0;
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc index ba2d1be..3c36532 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.cc
@@ -820,6 +820,17 @@ return reduced_user_agent_; } +String LocalFrameClientImpl::FullUserAgent() { + WebString override = + web_frame_->Client() ? web_frame_->Client()->UserAgentOverride() : ""; + if (!override.IsEmpty()) + return override; + + if (full_user_agent_.IsEmpty()) + full_user_agent_ = Platform::Current()->FullUserAgent(); + return full_user_agent_; +} + absl::optional<UserAgentMetadata> LocalFrameClientImpl::UserAgentMetadata() { bool ua_override_on = web_frame_->Client() && !web_frame_->Client()->UserAgentOverride().IsEmpty();
diff --git a/third_party/blink/renderer/core/frame/local_frame_client_impl.h b/third_party/blink/renderer/core/frame/local_frame_client_impl.h index 2d9517c..d78c1ed 100644 --- a/third_party/blink/renderer/core/frame/local_frame_client_impl.h +++ b/third_party/blink/renderer/core/frame/local_frame_client_impl.h
@@ -175,6 +175,7 @@ DocumentLoader* document_loader, std::unique_ptr<WebDocumentLoader::ExtraData> extra_data) override; WTF::String UserAgent() override; + WTF::String FullUserAgent() override; WTF::String ReducedUserAgent() override; absl::optional<blink::UserAgentMetadata> UserAgentMetadata() override; WTF::String DoNotTrackValue() override; @@ -302,6 +303,7 @@ Member<WebLocalFrameImpl> web_frame_; String user_agent_; + String full_user_agent_; String reduced_user_agent_; };
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc index 59a28e69..fd502ce 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.cc +++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
@@ -318,7 +318,7 @@ visitor->Trace(layout_subtree_root_list_); visitor->Trace(orthogonal_writing_mode_root_list_); visitor->Trace(fragment_anchor_); - visitor->Trace(scrollable_areas_); + visitor->Trace(scroll_anchoring_scrollable_areas_); visitor->Trace(animating_scrollable_areas_); visitor->Trace(user_scrollable_areas_); visitor->Trace(viewport_constrained_objects_); @@ -660,8 +660,8 @@ } LayoutState layout_state(root); - if (scrollable_areas_) { - for (auto& scrollable_area : *scrollable_areas_) { + if (scroll_anchoring_scrollable_areas_) { + for (auto& scrollable_area : *scroll_anchoring_scrollable_areas_) { if (scrollable_area->GetScrollAnchor() && scrollable_area->ShouldPerformScrollAnchoring()) scrollable_area->GetScrollAnchor()->NotifyBeforeLayout(); @@ -828,11 +828,7 @@ #if DCHECK_IS_ON() // Ensure fragment-tree consistency after a subtree layout. for (const auto& p : fragment_tree_spines) { - // |LayoutNGMixin::UpdateInFlowBlockLayout| may |SetNeedsLayout| to its - // containing block. Don't check if it will be re-laid out. - if (!p.key->NeedsLayout()) { - p.key->AssertFragmentTree(); - } + p.key->AssertFragmentTree(); DCHECK_EQ(p.value, 0u); } #endif @@ -1900,10 +1896,10 @@ if (!page) return; - if (!scrollable_areas_) + if (!user_scrollable_areas_) return; - for (const auto& scrollable_area : *scrollable_areas_) { + for (const auto& scrollable_area : *user_scrollable_areas_) { if (!scrollable_area->ScrollbarsCanBeActive()) continue; @@ -3610,21 +3606,20 @@ client->ScheduleAnimation(this, delay); } -void LocalFrameView::AddScrollableArea( +void LocalFrameView::AddScrollAnchoringScrollableArea( PaintLayerScrollableArea* scrollable_area) { DCHECK(scrollable_area); - if (!scrollable_areas_) - scrollable_areas_ = MakeGarbageCollected<ScrollableAreaSet>(); - scrollable_areas_->insert(scrollable_area); + if (!scroll_anchoring_scrollable_areas_) { + scroll_anchoring_scrollable_areas_ = + MakeGarbageCollected<ScrollableAreaSet>(); + } + scroll_anchoring_scrollable_areas_->insert(scrollable_area); } -void LocalFrameView::RemoveScrollableArea( +void LocalFrameView::RemoveScrollAnchoringScrollableArea( PaintLayerScrollableArea* scrollable_area) { - if (!scrollable_areas_) - return; - scrollable_areas_->erase(scrollable_area); - if (user_scrollable_areas_) - user_scrollable_areas_->erase(scrollable_area); + if (scroll_anchoring_scrollable_areas_) + scroll_anchoring_scrollable_areas_->erase(scrollable_area); } void LocalFrameView::AddAnimatingScrollableArea( @@ -3799,18 +3794,19 @@ ScrollableArea* LocalFrameView::ScrollableAreaWithElementId( const CompositorElementId& id) { - // Check for the layout viewport, which may not be in scrollable_areas_ if it - // is styled overflow: hidden. (Other overflow: hidden elements won't have - // composited scrolling layers per crbug.com/784053, so we don't have to worry - // about them.) + // Check for the layout viewport, which may not be in user_scrollable_areas_ + // if it is styled overflow: hidden. (Other overflow: hidden elements won't + // have composited scrolling layers per crbug.com/784053, so we don't have to + // worry about them.) ScrollableArea* viewport = LayoutViewport(); if (id == viewport->GetScrollElementId()) return viewport; - if (scrollable_areas_) { - // This requires iterating over all scrollable areas. We may want to store a - // map of ElementId to ScrollableArea if this is an issue for performance. - for (ScrollableArea* scrollable_area : *scrollable_areas_) { + if (user_scrollable_areas_) { + // This requires iterating over all user-scrollable areas. We may want to + // store a map of ElementId to ScrollableArea if this is an issue for + // performance. + for (ScrollableArea* scrollable_area : *user_scrollable_areas_) { if (id == scrollable_area->GetScrollElementId()) return scrollable_area; }
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.h b/third_party/blink/renderer/core/frame/local_frame_view.h index 5331e0e..0004cf03 100644 --- a/third_party/blink/renderer/core/frame/local_frame_view.h +++ b/third_party/blink/renderer/core/frame/local_frame_view.h
@@ -442,10 +442,10 @@ } using ScrollableAreaSet = HeapHashSet<Member<PaintLayerScrollableArea>>; - void AddScrollableArea(PaintLayerScrollableArea*); - void RemoveScrollableArea(PaintLayerScrollableArea*); - const ScrollableAreaSet* ScrollableAreas() const { - return scrollable_areas_.Get(); + void AddScrollAnchoringScrollableArea(PaintLayerScrollableArea*); + void RemoveScrollAnchoringScrollableArea(PaintLayerScrollableArea*); + const ScrollableAreaSet* ScrollAnchoringScrollableAreas() const { + return scroll_anchoring_scrollable_areas_.Get(); } void AddAnimatingScrollableArea(PaintLayerScrollableArea*); @@ -1033,15 +1033,9 @@ Member<FragmentAnchor> fragment_anchor_; - // Scrollable areas which either: - // - are user-scrollable, visible to hit testing, and do in fact overflow, or - // - overflow in the block flow direction (needed for LayoutFromRootObject() - // to get scroll anchoring right). - // TODO(abotella): According to skobes, every usage of scrollable_areas_ other - // than LayoutFromRootObject() can be switched to use user_scrollable_areas_. - // If so, scrollable_areas_ should probably be renamed and used only for areas - // which overflow in the block flow direction. - Member<ScrollableAreaSet> scrollable_areas_; + // Scrollable areas which overflow in the block flow direction. + // Needed for calculating scroll anchoring. + Member<ScrollableAreaSet> scroll_anchoring_scrollable_areas_; Member<ScrollableAreaSet> animating_scrollable_areas_; // Scrollable areas which are user-scrollable, whether they overflow or not. Member<ScrollableAreaSet> user_scrollable_areas_;
diff --git a/third_party/blink/renderer/core/html/forms/color_input_type.cc b/third_party/blink/renderer/core/html/forms/color_input_type.cc index 1bd8b6db..262612c5 100644 --- a/third_party/blink/renderer/core/html/forms/color_input_type.cc +++ b/third_party/blink/renderer/core/html/forms/color_input_type.cc
@@ -45,6 +45,7 @@ #include "third_party/blink/renderer/core/html/forms/html_option_element.h" #include "third_party/blink/renderer/core/html/html_div_element.h" #include "third_party/blink/renderer/core/input_type_names.h" +#include "third_party/blink/renderer/core/inspector/console_message.h" #include "third_party/blink/renderer/core/layout/layout_object.h" #include "third_party/blink/renderer/core/layout/layout_theme.h" #include "third_party/blink/renderer/core/page/chrome_client.h" @@ -148,8 +149,13 @@ return; Document& document = GetElement().GetDocument(); - if (!LocalFrame::HasTransientUserActivation(document.GetFrame())) + if (!LocalFrame::HasTransientUserActivation(document.GetFrame())) { + document.AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::blink::ConsoleMessageSource::kJavaScript, + mojom::blink::ConsoleMessageLevel::kWarning, + "A user gesture is required to show the color picker.")); return; + } ChromeClient* chrome_client = GetChromeClient(); if (chrome_client && !HasOpenedPopup()) {
diff --git a/third_party/blink/renderer/core/input/gesture_manager.cc b/third_party/blink/renderer/core/input/gesture_manager.cc index 9ec1e1e..63cdc8a 100644 --- a/third_party/blink/renderer/core/input/gesture_manager.cc +++ b/third_party/blink/renderer/core/input/gesture_manager.cc
@@ -519,7 +519,7 @@ LocalFrameView* view = frame_->View(); if (!view) return WebInputEventResult::kNotHandled; - const LocalFrameView::ScrollableAreaSet* areas = view->ScrollableAreas(); + const LocalFrameView::ScrollableAreaSet* areas = view->UserScrollableAreas(); if (!areas) return WebInputEventResult::kNotHandled; for (PaintLayerScrollableArea* scrollable_area : *areas) {
diff --git a/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc b/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc index ead25005..b7364c7 100644 --- a/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc +++ b/third_party/blink/renderer/core/inspector/dev_tools_emulator.cc
@@ -471,21 +471,6 @@ return transform; } -void DevToolsEmulator::OverrideVisibleRect( - const gfx::Size& viewport_size, - gfx::Rect* visible_rect_in_frame) const { - WebLocalFrameImpl* frame = web_view_->MainFrameImpl(); - if (!viewport_override_ || !frame) - return; - - // Don't apply viewport_override_->scale because all coordinates here are - // under the same scale. - gfx::Rect visible_rect_in_document = gfx::ToEnclosingRect( - gfx::RectF(viewport_override_->position, gfx::SizeF(viewport_size))); - *visible_rect_in_frame = - frame->GetFrameView()->DocumentToFrame(visible_rect_in_document); -} - float DevToolsEmulator::InputEventsScaleForEmulation() { return device_metrics_enabled_ ? emulation_params_.scale : 1.0; }
diff --git a/third_party/blink/renderer/core/inspector/dev_tools_emulator.h b/third_party/blink/renderer/core/inspector/dev_tools_emulator.h index 4ab39963..5c6562a 100644 --- a/third_party/blink/renderer/core/inspector/dev_tools_emulator.h +++ b/third_party/blink/renderer/core/inspector/dev_tools_emulator.h
@@ -15,7 +15,6 @@ namespace gfx { class PointF; -class Rect; } // namespace gfx namespace blink { @@ -70,14 +69,6 @@ // should only be called when HasViewportOverride() is true. TransformationMatrix MainFrameScrollOrScaleChanged(); - // Rewrites the |visible_rect| to the area of the devtools custom viewport if - // it is enabled. Otherwise, leaves |visible_rect| unchanged. Takes as input - // the size of the viewport, which gives an upper bound on the size of the - // area that is visible. The |viewport_size| is physical pixels if - // UseZoomForDSF() is enabled, or DIP otherwise. - void OverrideVisibleRect(const gfx::Size& viewport_size, - gfx::Rect* visible_rect) const; - // Returns the scale used to convert incoming input events while emulating // device metics. float InputEventsScaleForEmulation();
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index f8cb8572..a5784e6 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -442,6 +442,13 @@ void LayoutObject::AssertFragmentTree(bool display_locked) const { NOT_DESTROYED(); for (const LayoutObject* layout_object = this; layout_object;) { + // |LayoutNGMixin::UpdateInFlowBlockLayout| may |SetNeedsLayout| to its + // containing block. Don't check if it will be re-laid out. + if (layout_object->NeedsLayout()) { + layout_object = layout_object->NextInPreOrderAfterChildren(this); + continue; + } + // If display-locked, fragments may not be removed from the tree even after // the |LayoutObject| was destroyed, but still they should be consistent. if (!display_locked && layout_object->ChildLayoutBlockedByDisplayLock()) {
diff --git a/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.cc b/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.cc index 57e957e0..678f5324 100644 --- a/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.cc +++ b/third_party/blink/renderer/core/layout/ng/custom/layout_worklet_global_scope_proxy.cc
@@ -40,9 +40,11 @@ LocalFrameClient* frame_client = frame->Client(); const String user_agent = - RuntimeEnabledFeatures::UserAgentReductionEnabled(window) - ? frame_client->ReducedUserAgent() - : frame_client->UserAgent(); + RuntimeEnabledFeatures::SendFullUserAgentAfterReductionEnabled(window) + ? frame_client->FullUserAgent() + : RuntimeEnabledFeatures::UserAgentReductionEnabled(window) + ? frame_client->ReducedUserAgent() + : frame_client->UserAgent(); auto creation_params = std::make_unique<GlobalScopeCreationParams>( window->Url(), mojom::blink::ScriptType::kModule, global_scope_name,
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.cc index 392211e..20caee7 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.cc +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.cc
@@ -21,18 +21,31 @@ } // namespace -const Member<const NGBlockBreakToken>* -NGInlineBreakToken::BlockInInlineBreakTokenAddress() const { - CHECK(flags_ & kHasBlockInInlineToken); - return block_in_inline_break_token_; +const Member<const NGBreakToken>* NGInlineBreakToken::SubBreakTokenAddress() + const { + CHECK(flags_ & kHasSubBreakToken); + return sub_break_token_; } const NGBlockBreakToken* NGInlineBreakToken::BlockInInlineBreakToken() const { - if (!(flags_ & kHasBlockInInlineToken)) + if (!(flags_ & kHasSubBreakToken)) return nullptr; - const Member<const NGBlockBreakToken>* ptr = BlockInInlineBreakTokenAddress(); + const Member<const NGBreakToken>* ptr = SubBreakTokenAddress(); DCHECK(*ptr); - return ptr->Get(); + if ((*ptr)->IsBlockType()) + return To<NGBlockBreakToken>(ptr->Get()); + return nullptr; +} + +const NGInlineBreakToken* NGInlineBreakToken::SubBreakTokenInParallelFlow() + const { + if (!(flags_ & kHasSubBreakToken)) + return nullptr; + const Member<const NGBreakToken>* ptr = SubBreakTokenAddress(); + DCHECK(*ptr); + if ((*ptr)->IsInlineType()) + return To<NGInlineBreakToken>(ptr->Get()); + return nullptr; } // static @@ -42,19 +55,22 @@ unsigned item_index, unsigned text_offset, unsigned flags /* NGInlineBreakTokenFlags */, - const NGBlockBreakToken* block_in_inline_break_token) { + const NGBreakToken* sub_break_token) { // We store the children list inline in the break token as a flexible // array. Therefore, we need to make sure to allocate enough space for that // array here, which requires a manual allocation + placement new. wtf_size_t size = sizeof(NGInlineBreakToken); - if (UNLIKELY(block_in_inline_break_token)) { - size += sizeof(Member<const NGBlockBreakToken>); - flags |= kHasBlockInInlineToken; + if (UNLIKELY(sub_break_token)) { + if (sub_break_token->IsInlineType()) + size += sizeof(Member<const NGInlineBreakToken>); + else + size += sizeof(Member<const NGBlockBreakToken>); + flags |= kHasSubBreakToken; } return MakeGarbageCollected<NGInlineBreakToken>( AdditionalBytes(size), PassKey(), node, style, item_index, text_offset, - flags, block_in_inline_break_token); + flags, sub_break_token); } NGInlineBreakToken::NGInlineBreakToken( @@ -64,16 +80,19 @@ unsigned item_index, unsigned text_offset, unsigned flags /* NGInlineBreakTokenFlags */, - const NGBlockBreakToken* block_in_inline_break_token) + const NGBreakToken* sub_break_token) : NGBreakToken(kInlineBreakToken, node, flags), style_(style), item_index_(item_index), text_offset_(text_offset) { - if (UNLIKELY(block_in_inline_break_token)) { - const Member<const NGBlockBreakToken>* ptr = - BlockInInlineBreakTokenAddress(); - *const_cast<Member<const NGBlockBreakToken>*>(ptr) = - block_in_inline_break_token; + if (UNLIKELY(sub_break_token)) { +#if DCHECK_IS_ON() + // Only one level of inline break token nesting is expected. + DCHECK(!sub_break_token->IsInlineType() || + To<NGInlineBreakToken>(sub_break_token)->BlockInInlineBreakToken()); +#endif + const Member<const NGBreakToken>* ptr = SubBreakTokenAddress(); + *const_cast<Member<const NGBreakToken>*>(ptr) = sub_break_token; } } @@ -104,8 +123,8 @@ void NGInlineBreakToken::Trace(Visitor* visitor) const { // It is safe to check flags_ here because it is a const value and initialized // in ctor. - if (flags_ & kHasBlockInInlineToken) - visitor->Trace(*block_in_inline_break_token_); + if (flags_ & kHasSubBreakToken) + visitor->Trace(*sub_break_token_); NGBreakToken::Trace(visitor); }
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h index fa23529..c8817f85 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_break_token.h
@@ -21,7 +21,7 @@ enum NGInlineBreakTokenFlags { kDefault = 0, kIsForcedBreak = 1 << 0, - kHasBlockInInlineToken = 1 << 1, + kHasSubBreakToken = 1 << 1, kUseFirstLineStyle = 1 << 2, kHasClonedBoxDecorations = 1 << 3, // When adding values, ensure |flags_| has enough storage. @@ -36,7 +36,7 @@ unsigned item_index, unsigned text_offset, unsigned flags /* NGInlineBreakTokenFlags */, - const NGBlockBreakToken* block_in_inline_break_token = nullptr); + const NGBreakToken* sub_break_token = nullptr); // The style at the end of this break token. The next line should start with // this style. @@ -64,6 +64,14 @@ // The BreakToken when a block-in-inline is block-fragmented. const NGBlockBreakToken* BlockInInlineBreakToken() const; + // The BreakToken for the inline break token that has a block in inline break + // token inside. This should be resumed in the next fragmentainer as a + // parallel flow. This happens when a block inside an inline is overflowed + // beyond what was available in the fragmentainer. Regular inline content will + // then still fit in the fragmentainer, while the block inside the inline will + // be resumed in the next fragmentainer. + const NGInlineBreakToken* SubBreakTokenInParallelFlow() const; + // True if the current position has open tags that has `box-decoration-break: // clone`. They should be cloned to the start of the next line. bool HasClonedBoxDecorations() const { @@ -77,7 +85,7 @@ unsigned item_index, unsigned text_offset, unsigned flags /* NGInlineBreakTokenFlags */, - const NGBlockBreakToken* block_in_inline_break_token); + const NGBreakToken* sub_break_token); explicit NGInlineBreakToken(PassKey, NGLayoutInputNode node); @@ -88,14 +96,14 @@ void Trace(Visitor*) const override; private: - const Member<const NGBlockBreakToken>* BlockInInlineBreakTokenAddress() const; + const Member<const NGBreakToken>* SubBreakTokenAddress() const; scoped_refptr<const ComputedStyle> style_; unsigned item_index_; unsigned text_offset_; - // This is an array of one item if |kHasBlockInInlineToken|, or zero. - Member<const NGBlockBreakToken> block_in_inline_break_token_[]; + // This is an array of one item if |kHasSubBreakToken|, or zero. + Member<const NGBreakToken> sub_break_token_[]; }; template <>
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 3f660408..da1ef93 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
@@ -2057,6 +2057,8 @@ } NGInlineItemResult* item_result = AddItem(item, line_info); + const NGBlockBreakToken* incoming_block_break_token = + break_token_ ? break_token_->BlockInInlineBreakToken() : nullptr; if (mode_ == NGLineBreakerMode::kContent) { // The exclusion spaces *must* match. If they don't we'll have an incorrect // layout (as it will potentially won't consider some preceeding floats). @@ -2065,11 +2067,9 @@ constraint_space_.ExclusionSpace().MoveAndUpdateDerivedGeometry( *exclusion_space_); - const NGBlockBreakToken* block_break_token = - break_token_ ? break_token_->BlockInInlineBreakToken() : nullptr; scoped_refptr<const NGLayoutResult> layout_result = NGBlockNode(To<LayoutBox>(item.GetLayoutObject())) - .Layout(constraint_space_, block_break_token); + .Layout(constraint_space_, incoming_block_break_token); line_info->SetBlockInInlineLayoutResult(layout_result); // Early exit if the layout didn't succeed. @@ -2096,8 +2096,20 @@ line_info->SetHasForcedBreak(); is_after_forced_break_ = true; trailing_whitespace_ = WhitespaceState::kNone; - if (!line_info->BlockInInlineBreakToken()) + if (const NGBlockBreakToken* outgoing_block_break_token = + line_info->BlockInInlineBreakToken()) { + // The block broke inside. If the block itself fits, but some content inside + // overflowed, and this happened for the first time, we now need to enter a + // parallel flow, i.e. resume the block-in-inline in the next fragmentainer, + // but continue layout of any actual inline content after the block-in- + // inline in the current fragmentainer. + if (outgoing_block_break_token->IsAtBlockEnd() && + (!incoming_block_break_token || + !incoming_block_break_token->IsAtBlockEnd())) + needs_new_parallel_flow_ = true; + } else { MoveToNextOf(item); + } state_ = LineBreakState::kDone; } @@ -2828,6 +2840,7 @@ } void NGLineBreaker::MoveToNextOf(const NGInlineItem& item) { + DCHECK(!needs_new_parallel_flow_); offset_ = item.EndOffset(); item_index_++; #if DCHECK_IS_ON() @@ -2841,6 +2854,7 @@ } void NGLineBreaker::MoveToNextOf(const NGInlineItemResult& item_result) { + DCHECK(!needs_new_parallel_flow_); offset_ = item_result.EndOffset(); item_index_ = item_result.item_index; DCHECK(item_result.item); @@ -2849,23 +2863,58 @@ } const NGInlineBreakToken* NGLineBreaker::CreateBreakToken( - const NGLineInfo& line_info) const { + const NGLineInfo& line_info) { +#if DCHECK_IS_ON() + DCHECK(!has_considered_creating_break_token_); + has_considered_creating_break_token_ = true; +#endif + DCHECK(current_style_); + const NGBreakToken* sub_break_token = line_info.BlockInInlineBreakToken(); const HeapVector<NGInlineItem>& items = Items(); DCHECK_LE(item_index_, items.size()); + // If we have reached the end, create no break token. if (item_index_ >= items.size()) return nullptr; + // If we've resumed a block-in-inline in a parallel flow, and didn't break + // again, we're done. A break token will be created in the main flow (if + // there's any left of it). + if (UNLIKELY(break_token_ && break_token_->BlockInInlineBreakToken())) { + if (break_token_->BlockInInlineBreakToken()->IsAtBlockEnd() && + !sub_break_token) + return nullptr; + } DCHECK_EQ(line_info.HasForcedBreak(), is_after_forced_break_); - return NGInlineBreakToken::Create( - node_, current_style_.get(), item_index_, offset_, + unsigned flags = (is_after_forced_break_ ? NGInlineBreakToken::kIsForcedBreak : 0) | - (line_info.UseFirstLineStyle() - ? NGInlineBreakToken::kUseFirstLineStyle - : 0) | - (cloned_box_decorations_count_ - ? NGInlineBreakToken::kHasClonedBoxDecorations - : 0), - line_info.BlockInInlineBreakToken()); + (line_info.UseFirstLineStyle() ? NGInlineBreakToken::kUseFirstLineStyle + : 0) | + (cloned_box_decorations_count_ + ? NGInlineBreakToken::kHasClonedBoxDecorations + : 0); + + if (needs_new_parallel_flow_) { + // We broke inside a block-in-inline for the first time. This will establish + // a parallel flow, so that the block can be resumed independently of inline + // content that might come after it. We'll now create an inline break token + // for the block-in-inline, and then (below) we'll wrap this inside another + // inline break token. The inner break token will be found by the caller, + // and shouldn't be resumed until we get to the next fragmentainer. The + // outer break token is used to resume regular inline layout after the block + // in inline in the current fragmentainer (and the block-in-inline part + // won't be seen there). + sub_break_token = + NGInlineBreakToken::Create(node_, current_style_.get(), item_index_, + offset_, flags, sub_break_token); + + // Move past the block in inline, since we stopped at it. This is where + // regular inline content will resume. + needs_new_parallel_flow_ = false; + MoveToNextOf(items[item_index_]); + } + + return NGInlineBreakToken::Create(node_, current_style_.get(), item_index_, + offset_, flags, sub_break_token); } void NGLineBreaker::PropagateBreakToken(const NGBlockBreakToken* token) {
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h index ad1cdf194..9b6ea63 100644 --- a/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h +++ b/third_party/blink/renderer/core/layout/ng/inline/ng_line_breaker.h
@@ -58,7 +58,8 @@ bool IsFinished() const { return item_index_ >= Items().size(); } // Create an NGInlineBreakToken for the last line returned by NextLine(). - const NGInlineBreakToken* CreateBreakToken(const NGLineInfo&) const; + // Only call once per instance. + const NGInlineBreakToken* CreateBreakToken(const NGLineInfo&); void PropagateBreakToken(const NGBlockBreakToken*); HeapVector<Member<const NGBlockBreakToken>>& PropagatedBreakTokens() { @@ -302,6 +303,15 @@ // True if ShouldCreateNewSvgSegment() should be called. bool needs_svg_segmentation_ = false; + // True if we need to establish a new parallel flow for contents inside a + // block-in-inline that overflowed the fragmentainer (although the + // block-in-inline itself didn't overflow). + bool needs_new_parallel_flow_ = false; + +#if DCHECK_IS_ON() + bool has_considered_creating_break_token_ = false; +#endif + const NGInlineItemsData& items_data_; // The text content of this node. This is same as |items_data_.text_content|
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc index ef19181..0472bd2 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -1973,9 +1973,24 @@ logical_offset, *layout_result, fragment, self_collapsing_child_had_clearance); - *previous_inline_break_token = - child.IsInline() ? To<NGInlineBreakToken>(physical_fragment.BreakToken()) - : nullptr; + if (child.IsInline()) { + const auto* inline_break_token = + To<NGInlineBreakToken>(physical_fragment.BreakToken()); + if (UNLIKELY(inline_break_token && + inline_break_token->BlockInInlineBreakToken())) { + if (inline_break_token->BlockInInlineBreakToken()->IsAtBlockEnd()) { + // We resumed a block in inline in a parallel flow, and broke + // again. This will have to wait until we get to the next + // fragmentainer. The break token has already been added to the fragment + // builder. + DCHECK(child_break_token); + inline_break_token = nullptr; + } + } + *previous_inline_break_token = inline_break_token; + } else { + *previous_inline_break_token = nullptr; + } // Update |lines_until_clamp_| from the LayoutResult. if (lines_until_clamp_) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc index 13937d5..116bca88 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.cc
@@ -67,6 +67,7 @@ #include "third_party/blink/renderer/core/layout/ng/table/ng_table_row_layout_algorithm.h" #include "third_party/blink/renderer/core/layout/ng/table/ng_table_section_layout_algorithm.h" #include "third_party/blink/renderer/core/layout/shapes/shape_outside_info.h" +#include "third_party/blink/renderer/core/layout/svg/layout_svg_root.h" #include "third_party/blink/renderer/core/layout/text_autosizer.h" #include "third_party/blink/renderer/core/mathml/mathml_element.h" #include "third_party/blink/renderer/core/mathml/mathml_fraction_element.h" @@ -1641,6 +1642,22 @@ return LogicalSize(); } +LogicalSize NGBlockNode::GetReplacedSizeOverrideIfAny( + const NGConstraintSpace& space) const { + DCHECK(IsReplaced()); + if (!box_->IsSVGRoot()) + return LogicalSize(); + const LayoutSVGRoot& svg_root = To<LayoutSVGRoot>(*box_); + LayoutSize size_override = svg_root.GetContainerSize(); + if (!size_override.IsEmpty()) { + return PhysicalSize(size_override) + .ConvertToLogical(Style().GetWritingMode()); + } + if (svg_root.IsEmbeddedThroughFrameContainingSVGDocument()) + return space.AvailableSize(); + return LogicalSize(); +} + absl::optional<TransformationMatrix> NGBlockNode::GetTransformForChildFragment( const NGPhysicalBoxFragment& child_fragment, PhysicalSize size) const {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_node.h b/third_party/blink/renderer/core/layout/ng/ng_block_node.h index d567b0e8..445251db 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_node.h +++ b/third_party/blink/renderer/core/layout/ng/ng_block_node.h
@@ -122,6 +122,10 @@ // Returns the aspect ratio of a replaced element. LogicalSize GetAspectRatio() const; + // SVG roots sometimes have sizing peculiarities that override regular sizing. + // Returns {0,0} if there's no override. + LogicalSize GetReplacedSizeOverrideIfAny(const NGConstraintSpace&) const; + // Returns the transform to apply to a child (e.g. for layout-overflow). absl::optional<TransformationMatrix> GetTransformForChildFragment( const NGPhysicalBoxFragment& child_fragment,
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 c8988e4..29878ab 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
@@ -107,11 +107,43 @@ child_break_tokens_.push_back(child_break_token); break; case NGPhysicalFragment::kFragmentLineBox: + const auto* inline_break_token = + To<NGInlineBreakToken>(child_break_token); + if (inline_break_token) { + // TODO(mstensho): Orphans / widows calculation is wrong when regular + // inline layout gets interrupted by a block-in-inline. We need to + // reset line_count_ when this happens. + if (UNLIKELY(inline_break_token->BlockInInlineBreakToken())) { + if (inline_break_token->BlockInInlineBreakToken()->IsAtBlockEnd()) { + // We were resuming a block in inline, and we broke again, and + // we're in a parallel flow. To be resumed in the next + // fragmentainer. + child_break_tokens_.push_back(inline_break_token); + break; + } + } + if (UNLIKELY(inline_break_token->SubBreakTokenInParallelFlow())) { + // We broke inside a block inside an inline which establised a + // parallel flow in the current fragmentainer. This creates two + // inline break tokens - one for the actual inline content to resume + // in the current fragmentainer, and one for the block-in-inline to + // resume in the next fragmentainer. Look inside the break token for + // actual inline layout (it will be picked up and resumed by the + // current layout algorithm), and take the sub break token with the + // block-in-inline and add it to the break token list, so that it + // gets resumed in the next fragmentainer. + const auto* sub_break_token = + inline_break_token->SubBreakTokenInParallelFlow(); + DCHECK(sub_break_token->BlockInInlineBreakToken()); + child_break_tokens_.push_back(sub_break_token); + } + } + // We only care about the break token from the last line box added. This // is where we'll resume if we decide to block-fragment. Note that // child_break_token is nullptr if this is the last line to be generated // from the node. - last_inline_break_token_ = To<NGInlineBreakToken>(child_break_token); + last_inline_break_token_ = inline_break_token; line_count_++; break; }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc index f8e0f24..bad3bbe7 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_length_utils.cc
@@ -866,6 +866,13 @@ if (node.IsFrame()) return LogicalSize(); + LogicalSize size_override = node.GetReplacedSizeOverrideIfAny(space); + if (!size_override.IsEmpty()) { + DCHECK_GE(size_override.block_size, border_padding.BlockSum()); + DCHECK_GE(size_override.inline_size, border_padding.InlineSum()); + return size_override; + } + const ComputedStyle& style = node.Style(); const EBoxSizing box_sizing = style.BoxSizingForAspectRatio(); const Length& block_length = style.LogicalHeight();
diff --git a/third_party/blink/renderer/core/layout/svg/layout_svg_root.h b/third_party/blink/renderer/core/layout/svg/layout_svg_root.h index c5ed549..de7611c3 100644 --- a/third_party/blink/renderer/core/layout/svg/layout_svg_root.h +++ b/third_party/blink/renderer/core/layout/svg/layout_svg_root.h
@@ -88,6 +88,11 @@ container_size_ = container_size; } + LayoutSize GetContainerSize() const { + NOT_DESTROYED(); + return container_size_; + } + // localToBorderBoxTransform maps local SVG viewport coordinates to local CSS // box coordinates. const AffineTransform& LocalToBorderBoxTransform() const {
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 6070214..2c8f125 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -463,6 +463,17 @@ .c_str(), SerializeBoolHeader(true)); } + + if (ShouldSendClientHint( + ClientHintsMode::kStandard, policy, resource_origin, is_1p_origin, + network::mojom::blink::WebClientHintsType::kFullUserAgent, + hints_preferences)) { + request.SetHttpHeaderField( + network::GetClientHintToNameMap() + .at(network::mojom::blink::WebClientHintsType::kFullUserAgent) + .c_str(), + SerializeBoolHeader(true)); + } } if (ShouldSendClientHint( @@ -691,13 +702,15 @@ base::FeatureList::IsEnabled(features::kAllowClientHintsToThirdParty)) { origin_ok = true; } else { - // For subresource requests, if the parent frame has Sec-CH-UA-Reduced, - // then send Sec-CH-UA-Reduced in the fetch request, regardless of the - // permissions policy. - origin_ok = type == network::mojom::blink::WebClientHintsType::kUAReduced || - (policy && policy->IsFeatureEnabledForOrigin( - GetClientHintToPolicyFeatureMap().at(type), - resource_origin)); + // For subresource requests, if the parent frame has Sec-CH-UA-Reduced or + // Sec-CH-UA-Full, then send Sec-CH-UA-Reduced or Sec-CH-UA-Full in the + // fetch request, regardless of the permissions policy. + origin_ok = + type == network::mojom::blink::WebClientHintsType::kUAReduced || + type == network::mojom::blink::WebClientHintsType::kFullUserAgent || + (policy && + policy->IsFeatureEnabledForOrigin( + GetClientHintToPolicyFeatureMap().at(type), resource_origin)); } if (!origin_ok)
diff --git a/third_party/blink/renderer/core/loader/empty_clients.h b/third_party/blink/renderer/core/loader/empty_clients.h index 8a08a07..9ea6cc0 100644 --- a/third_party/blink/renderer/core/loader/empty_clients.h +++ b/third_party/blink/renderer/core/loader/empty_clients.h
@@ -310,6 +310,7 @@ std::unique_ptr<WebDocumentLoader::ExtraData> extra_data) override {} String UserAgent() override { return ""; } + String FullUserAgent() override { return ""; } String ReducedUserAgent() override { return ""; } absl::optional<blink::UserAgentMetadata> UserAgentMetadata() override { return blink::UserAgentMetadata();
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 8628f3a..0270b454b 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.cc
@@ -361,7 +361,15 @@ network::GetClientHintToNameMap() .at(network::mojom::blink::WebClientHintsType::kUAReduced) .c_str()) == "?1"; - String user_agent = ua_reduced ? GetReducedUserAgent() : GetUserAgent(); + const bool ua_full = + request.HttpHeaderField( + network::GetClientHintToNameMap() + .at(network::mojom::blink::WebClientHintsType::kFullUserAgent) + .c_str()) == "?1"; + + String user_agent = + ua_full ? GetFullUserAgent() + : (ua_reduced ? GetReducedUserAgent() : GetUserAgent()); base::UmaHistogramBoolean("Blink.Fetch.ReducedUserAgent", ua_reduced); request.SetHTTPUserAgent(AtomicString(user_agent)); @@ -700,6 +708,12 @@ return GetFrame()->Loader().UserAgent(); } +String FrameFetchContext::GetFullUserAgent() const { + if (GetResourceFetcherProperties().IsDetached()) + return frozen_state_->user_agent; + return GetFrame()->Loader().FullUserAgent(); +} + String FrameFetchContext::GetReducedUserAgent() const { if (GetResourceFetcherProperties().IsDetached()) return frozen_state_->user_agent; @@ -739,15 +753,20 @@ if (GetResourceFetcherProperties().IsDetached()) return this; + // If the Sec-CH-UA-Full client hint header is set on the request, then the + // full User-Agent string should be set on the User-Agent request header. // If the Sec-CH-UA-Reduced client hint header is set on the request, then the // reduced User-Agent string should also be set on the User-Agent request // header. const ClientHintsPreferences& client_hints_prefs = GetClientHintsPreferences(); String user_agent = client_hints_prefs.ShouldSend( - network::mojom::WebClientHintsType::kUAReduced) - ? GetReducedUserAgent() - : GetUserAgent(); + network::mojom::WebClientHintsType::kFullUserAgent) + ? GetFullUserAgent() + : client_hints_prefs.ShouldSend( + network::mojom::WebClientHintsType::kUAReduced) + ? GetReducedUserAgent() + : GetUserAgent(); frozen_state_ = MakeGarbageCollected<FrozenState>( Url(), GetContentSecurityPolicy(), GetSiteForCookies(),
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 183200f2..06e0907 100644 --- a/third_party/blink/renderer/core/loader/frame_fetch_context.h +++ b/third_party/blink/renderer/core/loader/frame_fetch_context.h
@@ -194,6 +194,7 @@ WebContentSettingsClient* GetContentSettingsClient() const; Settings* GetSettings() const; String GetUserAgent() const; + String GetFullUserAgent() const; String GetReducedUserAgent() const; absl::optional<UserAgentMetadata> GetUserAgentMetadata() const; const PermissionsPolicy* GetPermissionsPolicy() const override;
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index e47f0bc6..d2998b3 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -1340,6 +1340,13 @@ return user_agent; } +String FrameLoader::FullUserAgent() const { + String user_agent = Client()->FullUserAgent(); + probe::ApplyUserAgentOverride(probe::ToCoreProbeSink(frame_->GetDocument()), + &user_agent); + return user_agent; +} + String FrameLoader::ReducedUserAgent() const { String user_agent = Client()->ReducedUserAgent(); probe::ApplyUserAgentOverride(probe::ToCoreProbeSink(frame_->GetDocument()),
diff --git a/third_party/blink/renderer/core/loader/frame_loader.h b/third_party/blink/renderer/core/loader/frame_loader.h index 203712f1..21c3343 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.h +++ b/third_party/blink/renderer/core/loader/frame_loader.h
@@ -142,6 +142,7 @@ void DidExplicitOpen(); String UserAgent() const; + String FullUserAgent() const; String ReducedUserAgent() const; absl::optional<blink::UserAgentMetadata> UserAgentMetadata() const;
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 635f916..4cf1733 100644 --- a/third_party/blink/renderer/core/loader/mixed_content_checker.cc +++ b/third_party/blink/renderer/core/loader/mixed_content_checker.cc
@@ -50,6 +50,7 @@ #include "third_party/blink/renderer/core/frame/local_frame_client.h" #include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/inspector/console_message.h" +#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h" #include "third_party/blink/renderer/core/loader/document_loader.h" #include "third_party/blink/renderer/core/loader/frame_fetch_context.h" #include "third_party/blink/renderer/core/loader/worker_fetch_context.h"
diff --git a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc index e202b25..44895d94 100644 --- a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc +++ b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.cc
@@ -424,13 +424,16 @@ DCHECK(frame_view_->GetFrame().Client()->IsLocalFrameClientImpl()); DCHECK(frame_view_->GetFrame().IsLocalRoot()); - mobile_friendliness_.bad_tap_targets_ratio = ComputeBadTapTargetsRatio(); - mobile_friendliness_.small_text_ratio = text_area_sizes_.SmallTextRatio(); - mobile_friendliness_.text_content_outside_viewport_percentage = - ComputeContentOutsideViewport(); - - frame_view_->DidChangeMobileFriendliness(mobile_friendliness_); frame_view_->UnregisterFromLifecycleNotifications(this); + frame_view_->DidChangeMobileFriendliness(MobileFriendliness{ + .viewport_device_width = viewport_device_width_, + .viewport_initial_scale_x10 = viewport_initial_scale_x10_, + .viewport_hardcoded_width = viewport_hardcoded_width_, + .allow_user_zoom = allow_user_zoom_, + .small_text_ratio = text_area_sizes_.SmallTextRatio(), + .text_content_outside_viewport_percentage = + ComputeContentOutsideViewport(), + .bad_tap_targets_ratio = ComputeBadTapTargetsRatio()}); last_evaluated_ = base::TimeTicks::Now(); } @@ -443,29 +446,25 @@ return; const double zoom = viewport.zoom_is_explicit ? viewport.zoom : 1.0; - mobile_friendliness_.viewport_device_width = - viewport.max_width.IsDeviceWidth(); + viewport_device_width_ = viewport.max_width.IsDeviceWidth(); if (viewport.max_width.IsFixed()) { - mobile_friendliness_.viewport_hardcoded_width = - viewport.max_width.GetFloatValue(); + viewport_hardcoded_width_ = viewport.max_width.GetFloatValue(); // Convert value from Blink space to device-independent pixels. const double viewport_scalar = frame_view_->GetPage()->GetChromeClient().WindowToViewportScalar( &frame_view_->GetFrame(), 1); if (viewport_scalar != 0) - mobile_friendliness_.viewport_hardcoded_width /= viewport_scalar; + viewport_hardcoded_width_ /= viewport_scalar; } - if (viewport.zoom_is_explicit) { - mobile_friendliness_.viewport_initial_scale_x10 = - std::round(viewport.zoom * 10); - } + if (viewport.zoom_is_explicit) + viewport_initial_scale_x10_ = std::round(viewport.zoom * 10); if (viewport.user_zoom_is_explicit) { - mobile_friendliness_.allow_user_zoom = viewport.user_zoom; + allow_user_zoom_ = viewport.user_zoom; // If zooming is only allowed slightly. if (viewport.max_zoom / zoom < kMaximumScalePreventsZoomingThreshold) - mobile_friendliness_.allow_user_zoom = false; + allow_user_zoom_ = false; } }
diff --git a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h index 28efc3b..2429b52 100644 --- a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h +++ b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker.h
@@ -37,9 +37,6 @@ void WillBeRemovedFromFrame(); void NotifyViewportUpdated(const ViewportDescription&); void NotifyInvalidatePaint(const LayoutObject& object); - const blink::MobileFriendliness& GetMobileFriendliness() const { - return mobile_friendliness_; - } void Trace(Visitor* visitor) const override; struct TextAreaWithFontSize { @@ -61,11 +58,14 @@ int ComputeBadTapTargetsRatio(); private: - TextAreaWithFontSize text_area_sizes_; Member<LocalFrameView> frame_view_; - MobileFriendliness mobile_friendliness_; HeapTaskRunnerTimer<MobileFriendlinessChecker> timer_; base::TimeTicks last_evaluated_; + TextAreaWithFontSize text_area_sizes_; + bool viewport_device_width_ = false; + bool allow_user_zoom_ = -1; + int viewport_initial_scale_x10_ = -1; + int viewport_hardcoded_width_ = -1; }; } // namespace blink
diff --git a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc index 86c0566..3cf3c3a 100644 --- a/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc +++ b/third_party/blink/renderer/core/mobile_metrics/mobile_friendliness_checker_test.cc
@@ -509,6 +509,25 @@ EXPECT_GE(actual_mf.text_content_outside_viewport_percentage, 50); } +TEST_F(MobileFriendlinessCheckerTest, SmallTextByWideTable) { + // Wide image forces Chrome to zoom out. + MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"( +<html> + <body style="font-size: 12pt"> + <table> + <tr> + <td width=100px>a</td> + <td width=100px>b</td> + <td width=100px>c</td> + </tr> + </table> + </body> +</html> +)"); + EXPECT_EQ(actual_mf.small_text_ratio, 100); + EXPECT_GE(actual_mf.text_content_outside_viewport_percentage, 0); +} + TEST_F(MobileFriendlinessCheckerTest, NormalTextAndWideImageWithDeviceWidthViewport) { MobileFriendliness actual_mf = CalculateMetricsForHTMLString(R"(
diff --git a/third_party/blink/renderer/core/page/chrome_client.h b/third_party/blink/renderer/core/page/chrome_client.h index 337ca44..7db8d0b 100644 --- a/third_party/blink/renderer/core/page/chrome_client.h +++ b/third_party/blink/renderer/core/page/chrome_client.h
@@ -309,11 +309,6 @@ virtual void SetCursorForPlugin(const ui::Cursor&, LocalFrame*) = 0; - // Returns a custom visible rect if a viewport override is active. Requires - // the |frame| being painted, but only supports being used for the main frame. - virtual void OverrideVisibleRectForMainFrame(LocalFrame& frame, - gfx::Rect* paint_rect) const {} - // Returns the scale used to convert incoming input events while emulating // device metics. virtual float InputEventsScaleForEmulation() const { return 1; }
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 edc4e57..dc5f2b79 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl.cc
@@ -532,15 +532,6 @@ return frame.GetWidgetForLocalRoot()->GetScreenInfos(); } -void ChromeClientImpl::OverrideVisibleRectForMainFrame( - LocalFrame& frame, - gfx::Rect* visible_rect) const { - DCHECK(web_view_); - DCHECK(frame.IsMainFrame()); - return web_view_->GetDevToolsEmulator()->OverrideVisibleRect( - frame.GetWidgetForLocalRoot()->ViewRect().size(), visible_rect); -} - float ChromeClientImpl::InputEventsScaleForEmulation() const { DCHECK(web_view_); return web_view_->GetDevToolsEmulator()->InputEventsScaleForEmulation();
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl.h b/third_party/blink/renderer/core/page/chrome_client_impl.h index 38fdd4c..ec5b0f1 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl.h +++ b/third_party/blink/renderer/core/page/chrome_client_impl.h
@@ -142,8 +142,6 @@ float WindowToViewportScalar(LocalFrame*, const float) const override; const display::ScreenInfo& GetScreenInfo(LocalFrame&) const override; const display::ScreenInfos& GetScreenInfos(LocalFrame&) const override; - void OverrideVisibleRectForMainFrame(LocalFrame& frame, - gfx::Rect* paint_rect) const override; float InputEventsScaleForEmulation() const override; void ContentsSizeChanged(LocalFrame*, const gfx::Size&) const override; bool DoubleTapToZoomEnabled() const override;
diff --git a/third_party/blink/renderer/core/page/page.cc b/third_party/blink/renderer/core/page/page.cc index 546ab36..c1339aa 100644 --- a/third_party/blink/renderer/core/page/page.cc +++ b/third_party/blink/renderer/core/page/page.cc
@@ -792,7 +792,7 @@ // Iterate through all of the scrollable areas and mark their layout // objects for layout. if (LocalFrameView* view = local_frame->View()) { - if (const auto* scrollable_areas = view->ScrollableAreas()) { + if (const auto* scrollable_areas = view->UserScrollableAreas()) { for (const auto& scrollable_area : *scrollable_areas) { if (scrollable_area->ScrollsOverflow()) { if (auto* layout_box = scrollable_area->GetLayoutBox()) { @@ -872,7 +872,7 @@ continue; // Mark all scrollable areas as needing a paint property update because the // compositing reasons may have changed. - if (const auto* areas = local_frame->View()->ScrollableAreas()) { + if (const auto* areas = local_frame->View()->UserScrollableAreas()) { for (const auto& scrollable_area : *areas) { if (scrollable_area->ScrollsOverflow()) { if (auto* layout_box = scrollable_area->GetLayoutBox())
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 3a55bba5..b9fd1b7 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
@@ -195,7 +195,7 @@ if (LocalFrame* frame = GetLayoutBox()->GetFrame()) { if (LocalFrameView* frame_view = frame->View()) { - frame_view->RemoveScrollableArea(this); + frame_view->RemoveScrollAnchoringScrollableArea(this); frame_view->RemoveUserScrollableArea(this); frame_view->RemoveAnimatingScrollableArea(this); } @@ -2313,6 +2313,13 @@ ? HasVerticalOverflow() : HasHorizontalOverflow(); + if (overflows_in_block_direction) { + DCHECK(CanHaveOverflowScrollbars(*GetLayoutBox())); + frame_view->AddScrollAnchoringScrollableArea(this); + } else { + frame_view->RemoveScrollAnchoringScrollableArea(this); + } + bool is_visible_to_hit_test = GetLayoutBox()->StyleRef().VisibleToHitTesting(); bool did_scroll_overflow = scrolls_overflow_; @@ -2326,14 +2333,6 @@ } scrolls_overflow_ = has_overflow && is_visible_to_hit_test; - - if (scrolls_overflow_ || overflows_in_block_direction) { - DCHECK(CanHaveOverflowScrollbars(*GetLayoutBox())); - frame_view->AddScrollableArea(this); - } else { - frame_view->RemoveScrollableArea(this); - } - if (did_scroll_overflow == ScrollsOverflow()) return; @@ -2375,6 +2374,13 @@ // (see: BoxPainter::PaintBoxDecorationBackground). GetLayoutBox()->SetBackgroundNeedsFullPaintInvalidation(); + if (scrolls_overflow_) { + DCHECK(CanHaveOverflowScrollbars(*GetLayoutBox())); + frame_view->AddUserScrollableArea(this); + } else { + frame_view->RemoveUserScrollableArea(this); + } + layer_->DidUpdateScrollsOverflow(); }
diff --git a/third_party/blink/renderer/core/testing/internals.cc b/third_party/blink/renderer/core/testing/internals.cc index 1545a7c..0f738bf0 100644 --- a/third_party/blink/renderer/core/testing/internals.cc +++ b/third_party/blink/renderer/core/testing/internals.cc
@@ -951,8 +951,8 @@ IsA<Document>(node2) ? static_cast<const TreeScope*>(To<Document>(node2)) : IsA<ShadowRoot>(node2) - ? static_cast<const TreeScope*>(To<ShadowRoot>(node2)) - : nullptr; + ? static_cast<const TreeScope*>(To<ShadowRoot>(node2)) + : nullptr; if (!tree_scope1 || !tree_scope2) { exception_state.ThrowDOMException( DOMExceptionCode::kInvalidAccessError, @@ -2422,8 +2422,8 @@ unsigned count = 0; LocalFrame* frame = document->GetFrame(); - if (frame->View()->ScrollableAreas()) { - for (const auto& scrollable_area : *frame->View()->ScrollableAreas()) { + if (frame->View()->UserScrollableAreas()) { + for (const auto& scrollable_area : *frame->View()->UserScrollableAreas()) { if (scrollable_area->ScrollsOverflow()) count++; } @@ -2433,9 +2433,9 @@ child = child->Tree().NextSibling()) { auto* child_local_frame = DynamicTo<LocalFrame>(child); if (child_local_frame && child_local_frame->View() && - child_local_frame->View()->ScrollableAreas()) { + child_local_frame->View()->UserScrollableAreas()) { for (const auto& scrollable_area : - *child_local_frame->View()->ScrollableAreas()) { + *child_local_frame->View()->UserScrollableAreas()) { if (scrollable_area->ScrollsOverflow()) count++; }
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc index 4228a292..20ee543 100644 --- a/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc +++ b/third_party/blink/renderer/core/workers/threaded_worklet_messaging_proxy.cc
@@ -60,10 +60,14 @@ DCHECK(csp); LocalFrameClient* frame_client = window->GetFrame()->Client(); + // For now we should prioritize to send full UA string if opted into both + // Reduction and SendFullUserAgentAfterReduction Origin Trial const String user_agent = - RuntimeEnabledFeatures::UserAgentReductionEnabled(window) - ? frame_client->ReducedUserAgent() - : frame_client->UserAgent(); + RuntimeEnabledFeatures::SendFullUserAgentAfterReductionEnabled(window) + ? frame_client->FullUserAgent() + : (RuntimeEnabledFeatures::UserAgentReductionEnabled(window) + ? frame_client->ReducedUserAgent() + : frame_client->UserAgent()); auto global_scope_creation_params = std::make_unique<GlobalScopeCreationParams>(
diff --git a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc index 0163f5b..2acf0a5 100644 --- a/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc +++ b/third_party/blink/renderer/core/workers/worker_or_worklet_global_scope.cc
@@ -24,6 +24,7 @@ #include "third_party/blink/renderer/core/frame/deprecation.h" #include "third_party/blink/renderer/core/frame/policy_container.h" #include "third_party/blink/renderer/core/inspector/console_message.h" +#include "third_party/blink/renderer/core/inspector/inspector_audits_issue.h" #include "third_party/blink/renderer/core/loader/loader_factory_for_worker.h" #include "third_party/blink/renderer/core/loader/modulescript/module_script_fetch_request.h" #include "third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h"
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.cc b/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.cc index 392bc31..ecf1813 100644 --- a/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.cc +++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.cc
@@ -61,8 +61,8 @@ return cros_hid_.get(); } -ScriptPromise CrosHID::requestDevice(ScriptState* script_state, - const HIDDeviceRequestOptions* options) { +ScriptPromise CrosHID::accessDevice(ScriptState* script_state, + const HIDDeviceRequestOptions* options) { auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state); auto* cros_hid = GetCrosHIDOrNull();
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.h b/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.h index 40356696..81d9492 100644 --- a/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.h +++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.h
@@ -24,8 +24,8 @@ void Trace(Visitor*) const override; - ScriptPromise requestDevice(ScriptState* script_state, - const HIDDeviceRequestOptions*); + ScriptPromise accessDevice(ScriptState* script_state, + const HIDDeviceRequestOptions*); private: // Returns the remote for communication with the browser's HID
diff --git a/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.idl b/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.idl index 6399e0e4..1a38b698 100644 --- a/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.idl +++ b/third_party/blink/renderer/extensions/chromeos/system_extensions/hid/cros_hid.idl
@@ -3,6 +3,6 @@ // found in the LICENSE file. interface CrosHID { - [CallWith=ScriptState] Promise<sequence<HIDDevice>> requestDevice( + [CallWith=ScriptState] Promise<sequence<HIDDevice>> accessDevice( HIDDeviceRequestOptions options); -}; \ No newline at end of file +};
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc index 6410329..7025465 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
@@ -757,6 +757,19 @@ // TODO(accessibility) Consider forcing all ax objects to be created from // the top down, eliminating the need for ComputeParent(). AXObject* AXObject::ComputeParent() const { + AXObject* ax_parent = ComputeParentOrNull(); + + CHECK(!ax_parent || !ax_parent->IsDetached()) + << "Computed parent should never be detached:" + << "\n* Child: " << GetNode() + << "\n* Parent: " << ax_parent->ToString(true, true); + + return ax_parent; +} + +// Same as ComputeParent, but without the extra check for valid parent in the +// end. This is for use in RestoreParentOrPrune. +AXObject* AXObject::ComputeParentOrNull() const { #if defined(AX_FAIL_FAST_BUILD) SANITIZER_CHECK(!IsDetached()); @@ -784,11 +797,6 @@ ComputeNonARIAParent(AXObjectCache(), GetNode(), GetLayoutObject()); } - CHECK(!ax_parent || !ax_parent->IsDetached()) - << "Computed parent should never be detached:" - << "\n* Child: " << GetNode() - << "\n* Parent: " << ax_parent->ToString(true, true); - return ax_parent; }
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.h b/third_party/blink/renderer/modules/accessibility/ax_object.h index 93849ca..1d8b4bb 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object.h
@@ -1062,6 +1062,10 @@ // the parent. It calls ComputeParentImpl() for the actual work. AXObject* ComputeParent() const; + // Same as ComputeParent, but does not assert if there is no parent to compute + // (i.e. because the parent does not belong to the tree anymore). + AXObject* ComputeParentOrNull() const; + // Can this node be used to compute the natural parent of an object? // These are objects that can have some children, but the children are // only of a certain type or from another part of the tree, and therefore
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc index 05da7db..b67d028 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.cc
@@ -602,10 +602,8 @@ } void AXObjectCacheImpl::Dispose() { -#if DCHECK_IS_ON() DCHECK(!has_been_disposed_) << "Something is wrong, trying to dispose twice."; has_been_disposed_ = true; -#endif for (auto& entry : objects_) { AXObject* obj = entry.value; @@ -3494,7 +3492,7 @@ } AXObject* AXObjectCacheImpl::RestoreParentOrPrune(AXObject* child) { - AXObject* parent = child->ComputeParent(); + AXObject* parent = child->ComputeParentOrNull(); if (parent) child->SetParent(parent); else // If no parent is possible, the child is no longer part of the tree.
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h index e88f2381..55433d1 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h +++ b/third_party/blink/renderer/modules/accessibility/ax_object_cache_impl.h
@@ -352,9 +352,7 @@ const LayoutObject& layout_object); static bool IsRelevantSlotElement(const HTMLSlotElement& slot); -#if DCHECK_IS_ON() bool HasBeenDisposed() { return has_been_disposed_; } -#endif // Retrieves a vector of all AXObjects whose bounding boxes may have changed // since the last query. Clears the vector so that the next time it's @@ -495,10 +493,8 @@ std::unique_ptr<AXRelationCache> relation_cache_; -#if DCHECK_IS_ON() // Verified when finalizing. bool has_been_disposed_ = false; -#endif HeapVector<Member<AXEventParams>> notifications_to_post_main_; HeapVector<Member<AXEventParams>> notifications_to_post_popup_;
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object_test.cc b/third_party/blink/renderer/modules/accessibility/ax_object_test.cc index b10930f..8cd9a23 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_object_test.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_object_test.cc
@@ -1534,7 +1534,7 @@ ASSERT_FALSE(GetAXObjectByElementId("span-hidden")->CanSetFocusAttribute()); ASSERT_FALSE(GetAXObjectByElementId("a-hidden")->CanSetFocusAttribute()); - // ...nor if expressly inert... + // ...nor if inert... ASSERT_FALSE(GetAXObjectByElementId("div-inert")->CanSetFocusAttribute()); ASSERT_FALSE(GetAXObjectByElementId("span-inert")->CanSetFocusAttribute()); ASSERT_FALSE(GetAXObjectByElementId("a-inert")->CanSetFocusAttribute());
diff --git a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc index 41ee3a1..cb18ecc 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc +++ b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.cc
@@ -243,10 +243,8 @@ // Don't do this if it's also in the newly owned ids, as it's about to // get a new parent, and we want to avoid accidentally pruning it. if (!newly_owned_ids.Contains(removed_child_id)) { - if (AXObject* real_parent = - object_cache_->RestoreParentOrPrune(removed_child)) { - ChildrenChanged(real_parent); - } + MaybeRestoreParentOfOwnedChild(removed_child); + // Now that the child is not owned, it's "included in tree" state must // be recomputed because while owned children are always included in the // tree, unowned children may not be included. @@ -567,11 +565,24 @@ // |obj_id| owned others: if (aria_owner_to_children_mapping_.Contains(obj_id)) { - // |obj_id| longer owns anything. + // |obj_id| no longer owns anything. Vector<AXID> child_axids = aria_owner_to_children_mapping_.at(obj_id); aria_owned_child_to_owner_mapping_.RemoveAll(child_axids); // Owned children are no longer owned by |obj_id| aria_owner_to_children_mapping_.erase(obj_id); + // When removing nodes in AXObjectCacheImpl::Dispose we do not need to + // reparent (that could anyway fail trying to attach to an already removed + // node. + // TODO(jdapena@igalia.com): explore if we can skip all processing of the + // mappings in AXRelationCache in dispose case. + if (!object_cache_->HasBeenDisposed()) { + for (const auto& child_axid : child_axids) { + if (AXObject* owned_child = ObjectFromAXID(child_axid)) { + owned_child->DetachFromParent(); + MaybeRestoreParentOfOwnedChild(owned_child); + } + } + } } // Another id owned |obj_id|: @@ -625,4 +636,12 @@ } } +void AXRelationCache::MaybeRestoreParentOfOwnedChild(AXObject* child) { + DCHECK(child); + if (child->IsDetached()) + return; + if (AXObject* new_parent = object_cache_->RestoreParentOrPrune(child)) + ChildrenChanged(new_parent); +} + } // namespace blink
diff --git a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h index 8a7c8d0..066499d 100644 --- a/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h +++ b/third_party/blink/renderer/modules/accessibility/ax_relation_cache.h
@@ -126,6 +126,7 @@ void MapOwnedChildren(const AXObject* owner, const Vector<AXID>&); void GetReverseRelated(Node*, HeapVector<Member<AXObject>>& sources); + void MaybeRestoreParentOfOwnedChild(AXObject* removed_child); // Updates |aria_owner_to_children_mapping_| after calling UpdateAriaOwns for // either the content attribute or the attr associated elements.
diff --git a/third_party/blink/renderer/modules/buckets/storage_bucket_manager.cc b/third_party/blink/renderer/modules/buckets/storage_bucket_manager.cc index c845140c..062b3ae 100644 --- a/third_party/blink/renderer/modules/buckets/storage_bucket_manager.cc +++ b/third_party/blink/renderer/modules/buckets/storage_bucket_manager.cc
@@ -10,6 +10,7 @@ #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/execution_context/navigator_base.h" #include "third_party/blink/renderer/modules/buckets/storage_bucket.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/weborigin/security_origin.h" #include "third_party/blink/renderer/platform/wtf/functional.h"
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc index 1a09792..419fd246 100644 --- a/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc +++ b/third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope_proxy.cc
@@ -38,9 +38,11 @@ LocalFrameClient* frame_client = frame->Client(); const String user_agent = - RuntimeEnabledFeatures::UserAgentReductionEnabled(window) - ? frame_client->ReducedUserAgent() - : frame_client->UserAgent(); + RuntimeEnabledFeatures::SendFullUserAgentAfterReductionEnabled(window) + ? frame_client->FullUserAgent() + : RuntimeEnabledFeatures::UserAgentReductionEnabled(window) + ? frame_client->ReducedUserAgent() + : frame_client->UserAgent(); auto creation_params = std::make_unique<GlobalScopeCreationParams>( window->Url(), mojom::blink::ScriptType::kModule, global_scope_name,
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc b/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc index 61b39f48..b038e7a4 100644 --- a/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc +++ b/third_party/blink/renderer/modules/file_system_access/file_system_directory_handle.cc
@@ -12,6 +12,7 @@ #include "third_party/blink/public/mojom/file_system_access/file_system_access_manager.mojom-blink.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_directory_handle.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_get_directory_options.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_file_system_get_file_options.h" @@ -92,8 +93,10 @@ ScriptPromise result = resolver->Promise(); if (!mojo_ptr_.is_bound()) { - resolver->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kInvalidStateError)); + // TODO(crbug.com/1293949): Add an error message. + resolver->Reject(V8ThrowDOMException::CreateOrDie( + resolver->GetScriptState()->GetIsolate(), + DOMExceptionCode::kInvalidStateError, "")); return result; } @@ -129,8 +132,10 @@ ScriptPromise result = resolver->Promise(); if (!mojo_ptr_.is_bound()) { - resolver->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kInvalidStateError)); + // TODO(crbug.com/1293949): Add an error message. + resolver->Reject(V8ThrowDOMException::CreateOrDie( + resolver->GetScriptState()->GetIsolate(), + DOMExceptionCode::kInvalidStateError, "")); return result; } @@ -166,8 +171,10 @@ ScriptPromise result = resolver->Promise(); if (!mojo_ptr_.is_bound()) { - resolver->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kInvalidStateError)); + // TODO(crbug.com/1293949): Add an error message. + resolver->Reject(V8ThrowDOMException::CreateOrDie( + resolver->GetScriptState()->GetIsolate(), + DOMExceptionCode::kInvalidStateError, "")); return result; } @@ -192,8 +199,10 @@ ScriptPromise result = resolver->Promise(); if (!mojo_ptr_.is_bound()) { - resolver->Reject(MakeGarbageCollected<DOMException>( - DOMExceptionCode::kInvalidStateError)); + // TODO(crbug.com/1293949): Add an error message. + resolver->Reject(V8ThrowDOMException::CreateOrDie( + resolver->GetScriptState()->GetIsolate(), + DOMExceptionCode::kInvalidStateError, "")); return result; }
diff --git a/third_party/blink/renderer/modules/font_access/font_manager.cc b/third_party/blink/renderer/modules/font_access/font_manager.cc index 0c379c4..3b95ee9 100644 --- a/third_party/blink/renderer/modules/font_access/font_manager.cc +++ b/third_party/blink/renderer/modules/font_access/font_manager.cc
@@ -12,6 +12,8 @@ #include "third_party/blink/public/common/font_access/font_enumeration_table.pb.h" #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_throw_dom_exception.h" #include "third_party/blink/renderer/bindings/modules/v8/v8_query_options.h" #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h" @@ -59,6 +61,12 @@ const Vector<String>& selection, FontEnumerationStatus status, base::ReadOnlySharedMemoryRegion region) { + DCHECK(resolver); + if (!IsInParallelAlgorithmRunnable(resolver->GetExecutionContext(), + resolver->GetScriptState())) + return; + + ScriptState::Scope script_state_scope(resolver->GetScriptState()); if (RejectPromiseIfNecessary(status, resolver)) return; @@ -107,29 +115,35 @@ case FontEnumerationStatus::kOk: break; case FontEnumerationStatus::kUnimplemented: - resolver->Reject(MakeGarbageCollected<DOMException>( + resolver->Reject(V8ThrowDOMException::CreateOrDie( + resolver->GetScriptState()->GetIsolate(), DOMExceptionCode::kNotSupportedError, "Not yet supported on this platform.")); return true; case FontEnumerationStatus::kCanceled: - resolver->Reject(MakeGarbageCollected<DOMException>( + resolver->Reject(V8ThrowDOMException::CreateOrDie( + resolver->GetScriptState()->GetIsolate(), DOMExceptionCode::kAbortError, "The user canceled the operation.")); return true; case FontEnumerationStatus::kNeedsUserActivation: - resolver->Reject(MakeGarbageCollected<DOMException>( + resolver->Reject(V8ThrowDOMException::CreateOrDie( + resolver->GetScriptState()->GetIsolate(), DOMExceptionCode::kSecurityError, "User activation is required.")); return true; case FontEnumerationStatus::kNotVisible: - resolver->Reject(MakeGarbageCollected<DOMException>( + resolver->Reject(V8ThrowDOMException::CreateOrDie( + resolver->GetScriptState()->GetIsolate(), DOMExceptionCode::kSecurityError, "Page needs to be visible.")); return true; case FontEnumerationStatus::kPermissionDenied: - resolver->Reject(MakeGarbageCollected<DOMException>( + resolver->Reject(V8ThrowDOMException::CreateOrDie( + resolver->GetScriptState()->GetIsolate(), DOMExceptionCode::kNotAllowedError, "Permission not granted.")); return true; case FontEnumerationStatus::kUnexpectedError: default: - resolver->Reject(MakeGarbageCollected<DOMException>( + resolver->Reject(V8ThrowDOMException::CreateOrDie( + resolver->GetScriptState()->GetIsolate(), DOMExceptionCode::kUnknownError, "An unexpected error occured.")); return true; }
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc index 3532a69..043cbd8 100644 --- a/third_party/blink/renderer/modules/payments/payment_request.cc +++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -600,8 +600,6 @@ if (exception_state.HadException()) return; if (input->hasTotal()) { - DCHECK(!RuntimeEnabledFeatures::DigitalGoodsEnabled(&execution_context) || - !ignore_total); if (ignore_total) { output->total = CreateTotalPlaceHolderForAppStoreBilling(execution_context);
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc index 7d6f8cae..6907c49 100644 --- a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc +++ b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
@@ -26,6 +26,7 @@ #include "third_party/blink/renderer/modules/webaudio/audio_param_timeline.h" #include <algorithm> +#include <limits> #include <memory> #include "base/memory/ptr_util.h" @@ -541,7 +542,6 @@ DCHECK(std::isfinite(event->Duration())); DCHECK_GE(event->Duration(), 0); - unsigned i = 0; double insert_time = event->Time(); if (!events_.size() && @@ -556,13 +556,39 @@ new_events_.insert(events_[0].get()); } - for (i = 0; i < events_.size(); ++i) { - if (event->GetType() == ParamEvent::kSetValueCurve) { - // If this event is a SetValueCurve, make sure it doesn't overlap any - // existing event. It's ok if the SetValueCurve starts at the same time as - // the end of some other duration. - double end_time = event->Time() + event->Duration(); + if (events_.IsEmpty()) { + events_.insert(0, std::move(event)); + new_events_.insert(events_[0].get()); + return; + } + + // Most of the time, we must insert after the last event. If the time of the + // last event is greater than the insert_time, use binary search to find the + // insertion point. + wtf_size_t insertion_idx = events_.size(); + DCHECK_GT(insertion_idx, wtf_size_t{0}); + wtf_size_t ub = insertion_idx - 1; // upper bound of events that can overlap. + if (events_.back()->Time() > insert_time) { + auto* it = std::upper_bound( + events_.begin(), events_.end(), insert_time, + [](const double value, const std::unique_ptr<ParamEvent>& entry) { + return value < entry->Time(); + }); + insertion_idx = static_cast<wtf_size_t>(std::distance(events_.begin(), it)); + DCHECK_LT(insertion_idx, events_.size()); + ub = insertion_idx; + } + DCHECK_LT(ub, static_cast<wtf_size_t>(std::numeric_limits<int>::max())); + + if (event->GetType() == ParamEvent::kSetValueCurve) { + double end_time = event->Time() + event->Duration(); + for (int i = ub; i >= 0; i--) { ParamEvent::Type test_type = events_[i]->GetType(); + // Events of type |kSetValueCurveEnd| or |kCancelValues| never conflict. + if (test_type == ParamEvent::kSetValueCurveEnd || + test_type == ParamEvent::kCancelValues) { + continue; + } if (test_type == ParamEvent::kSetValueCurve) { // A SetValueCurve overlapping an existing SetValueCurve requires // special care. @@ -581,10 +607,9 @@ EventToString(*events_[i])); return; } - } else if (test_type != ParamEvent::kSetValueCurveEnd && - test_type != ParamEvent::kCancelValues) { - // Events of type |kSetValueCurveEnd| or |kCancelValues| never - // conflict, so we handle only the other event types. + } else { + // Here we handle existing events of types other than + // |kSetValueCurveEnd|, |kCancelValues| and |kSetValueCurve|. // Throw an error if an existing event starts in the middle of this // SetValueCurve event. if (events_[i]->Time() > event->Time() && @@ -596,10 +621,28 @@ return; } } - } else { - // Otherwise, make sure this event doesn't overlap any existing - // SetValueCurve event. - if (events_[i]->GetType() == ParamEvent::kSetValueCurve) { + if (events_[i]->Time() < insert_time) { + // We found an existing event, E, of type other than |kSetValueCurveEnd| + // or |kCancelValues| that starts before the new event of type + // |kSetValueCurve| that we want to insert. No earlier existing event + // can overlap with the new event. An overlapping |kSetValueCurve| would + // have ovelapped with E too, so one of them would not be inserted. + // Other event types overlap with the new |kSetValueCurve| event only if + // they start in the middle of the new event, which is not the case. + break; + } + } + } else { + // Not a |SetValueCurve| new event. Make sure this new event doesn't overlap + // any existing |SetValueCurve| event. + for (int i = ub; i >= 0; i--) { + ParamEvent::Type test_type = events_[i]->GetType(); + // Events of type |kSetValueCurveEnd| or |kCancelValues| never conflict. + if (test_type == ParamEvent::kSetValueCurveEnd || + test_type == ParamEvent::kCancelValues) { + continue; + } + if (test_type == ParamEvent::kSetValueCurve) { double end_time = events_[i]->Time() + events_[i]->Duration(); if (event->GetType() != ParamEvent::kSetValueCurveEnd && event->Time() >= events_[i]->Time() && event->Time() < end_time) { @@ -610,15 +653,18 @@ return; } } - } - - if (events_[i]->Time() > insert_time) { - break; + if (events_[i]->Time() < insert_time) { + // We found an existing event, E, of type other than |kSetValueCurveEnd| + // or |kCancelValues| that starts before the new event that we want to + // insert. No earlier event of type |kSetValueCurve| can overlap with + // the new event, because it would have overlapped with E too. + break; + } } } - events_.insert(i, std::move(event)); - new_events_.insert(events_[i].get()); + events_.insert(insertion_idx, std::move(event)); + new_events_.insert(events_[insertion_idx].get()); } bool AudioParamTimeline::HasValues(size_t current_frame,
diff --git a/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.cc b/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.cc index 825c3cb..df04fd5 100644 --- a/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.cc +++ b/third_party/blink/renderer/modules/webcodecs/reclaimable_codec.cc
@@ -68,14 +68,23 @@ return; } - if (auto* pressure_manager = PressureManager()) + if (auto* pressure_manager = PressureManager()) { + // If we fail to get |pressure_manager| here (say, because the + // ExecutionContext is being destroyed), this is harmless. The + // CodecPressureManager maintains its own local pressure count, and it will + // properly decrement it from the global pressure count upon the manager's + // disposal. The CodecPressureManager's WeakMember reference to |this| will + // be cleared by the GC when |this| is disposed. The manager might still + // call into SetGlobalPressureExceededFlag() before |this| is disposed, but + // we will simply noop those calls. pressure_manager->RemoveCodec(this); - - is_applying_pressure_ = false; + } // We might still exceed global codec pressure at this point, but this codec // isn't contributing to it, and needs to reset its own flag. SetGlobalPressureExceededFlag(false); + + is_applying_pressure_ = false; } void ReclaimableCodec::Dispose() { @@ -88,6 +97,13 @@ void ReclaimableCodec::SetGlobalPressureExceededFlag( bool global_pressure_exceeded) { + if (!is_applying_pressure_) { + // We should only hit this call because we failed to get the + // PressureManager() in ReleaseCodecPressure(). See the note above. + DCHECK(!PressureManager()); + return; + } + if (global_pressure_exceeded_ == global_pressure_exceeded) return;
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_object.cc b/third_party/blink/renderer/modules/webgpu/dawn_object.cc index 0ffe2d1e..45403ab 100644 --- a/third_party/blink/renderer/modules/webgpu/dawn_object.cc +++ b/third_party/blink/renderer/modules/webgpu/dawn_object.cc
@@ -19,6 +19,20 @@ return dawn_control_client_; } +void DawnObjectBase::setLabel(ScriptState* script_state, + const ScriptValue value, + ExceptionState& exception_state) { + v8::Local<v8::Value> v8_value = value.V8Value(); + if (v8_value->IsString()) { + setLabel(ToCoreString(v8::Local<v8::String>::Cast(v8_value))); + } else if (v8_value->IsUndefined()) { + setLabel(String()); + } else { + exception_state.ThrowTypeError( + "'label' is not of type 'string' or undefined"); + } +} + void DawnObjectBase::setLabel(const String& value) { // TODO: Relay label changes to Dawn label_ = value;
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_object.h b/third_party/blink/renderer/modules/webgpu/dawn_object.h index 64f496a..bbcafde4 100644 --- a/third_party/blink/renderer/modules/webgpu/dawn_object.h +++ b/third_party/blink/renderer/modules/webgpu/dawn_object.h
@@ -9,6 +9,7 @@ #include <dawn/webgpu.h> #include "base/memory/scoped_refptr.h" +#include "third_party/blink/renderer/bindings/core/v8/script_value.h" #include "third_party/blink/renderer/platform/bindings/script_wrappable.h" #include "third_party/blink/renderer/platform/graphics/gpu/dawn_control_client_holder.h" #include "third_party/blink/renderer/platform/heap/member.h" @@ -89,7 +90,18 @@ void FlushNow(); // GPUObjectBase mixin implementation - const String& label() const { return label_; } + const ScriptValue label(ScriptState* script_state, + ExceptionState& exception_state) const { + if (label_.IsNull()) { + v8::Isolate* isolate = script_state->GetIsolate(); + return ScriptValue(isolate, v8::Undefined(isolate)); + } + return ScriptValue::From(script_state, label_); + } + void setLabel(ScriptState* script_state, + const ScriptValue value, + ExceptionState& exception_state); + void setLabel(const String& value); private:
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_object_base.idl b/third_party/blink/renderer/modules/webgpu/gpu_object_base.idl index cd9aa2d..b7ecf90 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_object_base.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_object_base.idl
@@ -5,5 +5,9 @@ // https://gpuweb.github.io/gpuweb/ interface mixin GPUObjectBase { - attribute USVString? label; + // TODO: The type should be (USVString or undefined) but + // the bindings can't handle it now although it should be valid type. + // As a workaround we make the type any and do custom handling in Blink + // until the bindings supports it. Refer to crbug.com/1293259. + [CallWith=ScriptState, RaisesException] attribute any label; }; \ No newline at end of file
diff --git a/third_party/blink/renderer/platform/media/key_system_config_selector.cc b/third_party/blink/renderer/platform/media/key_system_config_selector.cc index 7296579..fa06a896 100644 --- a/third_party/blink/renderer/platform/media/key_system_config_selector.cc +++ b/third_party/blink/renderer/platform/media/key_system_config_selector.cc
@@ -992,6 +992,9 @@ const WebString& key_system, const WebVector<WebMediaKeySystemConfiguration>& candidate_configurations, SelectConfigCB cb) { + DCHECK(key_systems_->IsUpToDate()) + << "The caller must make sure the Key Systems are up to date"; + // Continued from requestMediaKeySystemAccess(), step 6, from // https://w3c.github.io/encrypted-media/#requestmediakeysystemaccess // @@ -1003,8 +1006,6 @@ return; } - key_systems_->UpdateIfNeeded(); - std::string key_system_ascii = key_system.Ascii(); if (!key_systems_->IsSupportedKeySystem(key_system_ascii)) { std::move(cb).Run(Status::kUnsupportedKeySystem, nullptr, nullptr);
diff --git a/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc b/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc index 7e1ca0d..07e5650 100644 --- a/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc +++ b/third_party/blink/renderer/platform/media/key_system_config_selector_unittest.cc
@@ -198,7 +198,12 @@ public: ~FakeKeySystems() override = default; - void UpdateIfNeeded() override { ++update_count; } + void UpdateIfNeeded(base::OnceClosure done_cb) override { + NOTREACHED() << "Not needed since IsUpToDate() always returns true"; + std::move(done_cb).Run(); + } + + bool IsUpToDate() override { return true; } std::string GetBaseKeySystemName( const std::string& key_system) const override { @@ -363,8 +368,6 @@ // the default values may be changed. EmeFeatureSupport persistent_state = EmeFeatureSupport::NOT_SUPPORTED; EmeFeatureSupport distinctive_identifier = EmeFeatureSupport::REQUESTABLE; - - int update_count = 0; }; class FakeMediaPermission : public media::MediaPermission { @@ -565,17 +568,6 @@ EXPECT_FALSE(cdm_config_.use_hw_secure_codecs); } -// KeySystemConfigSelector should make sure it uses up-to-date KeySystems. -TEST_F(KeySystemConfigSelectorTest, UpdateKeySystems) { - configs_.push_back(UsableConfiguration()); - - ASSERT_EQ(key_systems_->update_count, 0); - SelectConfig(); - EXPECT_EQ(key_systems_->update_count, 1); - SelectConfig(); - EXPECT_EQ(key_systems_->update_count, 2); -} - TEST_F(KeySystemConfigSelectorTest, Label) { auto config = UsableConfiguration(); config.label = "foo";
diff --git a/third_party/blink/renderer/platform/media/web_encrypted_media_client_impl.cc b/third_party/blink/renderer/platform/media/web_encrypted_media_client_impl.cc index 90d723d..6a824434 100644 --- a/third_party/blink/renderer/platform/media/web_encrypted_media_client_impl.cc +++ b/third_party/blink/renderer/platform/media/web_encrypted_media_client_impl.cc
@@ -100,7 +100,8 @@ std::unique_ptr<KeySystemConfigSelector::WebLocalFrameDelegate> web_frame_delegate) : cdm_factory_(cdm_factory), - key_system_config_selector_(media::KeySystems::GetInstance(), + key_systems_(media::KeySystems::GetInstance()), + key_system_config_selector_(key_systems_, media_permission, std::move(web_frame_delegate)) { DCHECK(cdm_factory_); @@ -112,10 +113,15 @@ WebEncryptedMediaRequest request) { GetReporter(request.KeySystem())->ReportRequested(); - key_system_config_selector_.SelectConfig( - request.KeySystem(), request.SupportedConfigurations(), - base::BindOnce(&WebEncryptedMediaClientImpl::OnConfigSelected, - weak_factory_.GetWeakPtr(), request)); + if (!key_systems_->IsUpToDate()) { + pending_requests_.push_back(std::move(request)); + key_systems_->UpdateIfNeeded( + base::BindOnce(&WebEncryptedMediaClientImpl::OnKeySystemsUpdated, + weak_factory_.GetWeakPtr())); + return; + } + + SelectConfig(request); } void WebEncryptedMediaClientImpl::CreateCdm( @@ -128,6 +134,20 @@ std::move(result))); } +void WebEncryptedMediaClientImpl::OnKeySystemsUpdated() { + auto requests = std::move(pending_requests_); + for (const auto& request : requests) + SelectConfig(request); +} + +void WebEncryptedMediaClientImpl::SelectConfig( + WebEncryptedMediaRequest request) { + key_system_config_selector_.SelectConfig( + request.KeySystem(), request.SupportedConfigurations(), + base::BindOnce(&WebEncryptedMediaClientImpl::OnConfigSelected, + weak_factory_.GetWeakPtr(), request)); +} + void WebEncryptedMediaClientImpl::OnConfigSelected( WebEncryptedMediaRequest request, KeySystemConfigSelector::Status status,
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5 index 3f91a39b..9471a50 100644 --- a/third_party/blink/renderer/platform/runtime_enabled_features.json5 +++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
@@ -884,8 +884,8 @@ origin_trial_feature_name: "DigitalGoodsV2", origin_trial_os: ["android", "chromeos"], status: { - "Android": "experimental", - "ChromeOS": "experimental", + "Android": "stable", + "ChromeOS": "stable", // crbug.com/1143079: Web tests cannot differentiate ChromeOS and Linux, // so enable the API on all platforms for testing. "default": "test" @@ -2089,8 +2089,7 @@ { name: "SendFullUserAgentAfterReduction", origin_trial_feature_name: "SendFullUserAgentAfterReduction", - origin_trial_allows_third_party: true, - status: "experimental", + origin_trial_allows_third_party: true }, { name: "SendMouseEventsDisabledFormControls",
diff --git a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py index b568fb9..5f2036c 100644 --- a/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py +++ b/third_party/blink/tools/blinkpy/tool/commands/rebaseline_cl_unittest.py
@@ -267,8 +267,8 @@ def test_execute_with_test_name_file(self): fs = self.mac_port.host.filesystem test_name_file = fs.mktemp() - fs.write_text_file( - test_name_file, + file = fs.open_text_file_for_writing(test_name_file) + file.write( textwrap.dedent(''' one/flaky-fail.html one/missing.html @@ -293,8 +293,8 @@ def test_execute_with_test_name_file_resultDB(self): fs = self.mac_port.host.filesystem test_name_file = fs.mktemp() - fs.write_text_file( - test_name_file, + file = fs.open_text_file_for_writing(test_name_file) + file.write( textwrap.dedent(''' one/missing.html two/missing.html
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index eecc320..29476ada 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1916,7 +1916,7 @@ # @container crbug.com/1289850 external/wpt/css/css-contain/container-queries/canvas-as-container-004.html [ Failure ] crbug.com/1289850 external/wpt/css/css-contain/container-queries/canvas-as-container-006.html [ Failure ] -crbug.com/1273913 external/wpt/css/css-contain/container-queries/pseudo-elements-002.tentative.html [ Failure ] +crbug.com/1273913 external/wpt/css/css-contain/container-queries/pseudo-elements-002.html [ Failure ] # CSS Scrollbars crbug.com/891944 external/wpt/css/css-scrollbars/textarea-scrollbar-width-none.html [ Failure ] @@ -3190,6 +3190,13 @@ crbug.com/626703 [ Linux ] external/wpt/url/failure.html [ Failure ] # ====== New tests from wpt-importer added here ====== +crbug.com/626703 [ Win10.20h2 ] external/wpt/webrtc/RTCDataChannel-bufferedAmount.html [ Crash ] +crbug.com/626703 [ Mac11-arm64 ] virtual/not-site-per-process/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-no-child-yes-port.sub.https.html [ Timeout ] +crbug.com/626703 [ Mac11-arm64 ] virtual/not-site-per-process/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-yes-child-yes-port.sub.https.html [ Timeout ] +crbug.com/626703 [ Mac11-arm64 ] virtual/not-site-per-process/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/popups/opener-no-openee-yes-port.sub.https.html [ Timeout ] +crbug.com/626703 [ Mac10.12 ] virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-computed.html [ Failure Timeout ] +crbug.com/626703 [ Win10.20h2 ] virtual/webrtc-wpt-plan-b/external/wpt/webrtc/RTCDataChannel-bufferedAmount.html [ Crash ] +crbug.com/626703 [ Mac10.12 ] virtual/fenced-frame-mparch/wpt_internal/fenced_frame/background-fetch.https.html [ Timeout ] crbug.com/626703 [ Mac10.15 ] virtual/off-main-thread-css-paint/external/wpt/css/css-paint-api/geometry-border-image-001.https.html [ Failure ] crbug.com/626703 external/wpt/css/filter-effects/filter-function/filter-function-001.html [ Failure ] crbug.com/626703 external/wpt/css/filter-effects/filter-function/filter-function-002.html [ Failure ] @@ -3303,7 +3310,6 @@ crbug.com/626703 [ Mac11-arm64 ] virtual/plz-dedicated-worker/external/wpt/content-security-policy/inside-worker/serviceworker-report-only.https.sub.html [ Timeout ] crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/CSS2/normal-flow/width-081.xht [ Crash Failure ] crbug.com/626703 [ Mac11-arm64 ] external/wpt/css/css-contain/contain-layout-ignored-cases-no-principal-box-002.html [ Crash Failure ] -crbug.com/626703 [ Mac11-arm64 ] virtual/not-site-per-process/external/wpt/html/browsers/origin/origin-keyed-agent-clusters/1-iframe/parent-no-child-yes-port.sub.https.html [ Crash Failure ] crbug.com/626703 [ Mac11-arm64 ] external/wpt/fetch/api/basic/status.h2.any.worker.html [ Timeout ] crbug.com/626703 [ Mac11-arm64 ] external/wpt/infrastructure/server/http2-websocket.sub.h2.any.worker.html [ Timeout ] crbug.com/626703 [ Mac11-arm64 ] external/wpt/websockets/Close-1000-reason.any.worker.html?wpt_flags=h2 [ Timeout ]
diff --git a/third_party/blink/web_tests/VirtualTestSuites b/third_party/blink/web_tests/VirtualTestSuites index 54677d4..891914b 100644 --- a/third_party/blink/web_tests/VirtualTestSuites +++ b/third_party/blink/web_tests/VirtualTestSuites
@@ -116,6 +116,7 @@ "http/tests/navigation", "http/tests/sendbeacon", "http/tests/serviceworker/webexposed", + "http/tests/worklet/webexposed", "inspector-protocol/dom-snapshot", "media/stable", "webexposed",
diff --git a/third_party/blink/web_tests/external/Version b/third_party/blink/web_tests/external/Version index 3f55828..f36a8de 100644 --- a/third_party/blink/web_tests/external/Version +++ b/third_party/blink/web_tests/external/Version
@@ -1 +1 @@ -Version: b0f2a3d41dbcf8043d5438992851203b821f740b +Version: 9c5edd30ac28805430d0a7c1cbd09167636dbf2e
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json index 9f7a382..3be1360 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -505,6 +505,13 @@ ] ], "container-queries": { + "canvas-as-container-crash.html": [ + "8d825606561884090c74b63e3d7bdfef19709169", + [ + null, + {} + ] + ], "chrome-bug-1289718-000-crash.html": [ "5dab634a2a2586722ddbd0a9cf9eea8e31001dc6", [ @@ -78263,6 +78270,58 @@ {} ] ], + "block-in-inline-000.html": [ + "ae9ee3421b4e0e2971a4ba41033d9368525c5289", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-in-inline-001.html": [ + "de967599fe30e7debf002fb1ba5858060882e5b5", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-in-inline-002.html": [ + "c5e44c901c6ceda32d9f4fd81b0dc5608e43f7e8", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "block-in-inline-003.html": [ + "a276fde583903efe83545a6bb147ecf3f7bb3b28", + [ + null, + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "block-max-height-001.html": [ "acb4316d13eee6d791e8c27e5e1b8ab2be03e0ac", [ @@ -91479,13 +91538,13 @@ {} ] ], - "pseudo-elements-002.tentative.html": [ - "e46d25cf8754bd1ec277dda727fc88018af65126", + "pseudo-elements-002.html": [ + "a41bc43b9acc07e5e05c4e8adc940b4227ad1c0a", [ null, [ [ - "/css/css-contain/container-queries/pseudo-elements-002.tentative-ref.html", + "/css/css-contain/container-queries/pseudo-elements-002-ref.html", "==" ] ], @@ -244117,7 +244176,7 @@ ], "parsing": { "color-computed-expected.txt": [ - "a9c6646d7d9739fa774e22e74f13984dc598280e", + "d2901735005c041eb9c8d85d4383387641a05632", [] ], "color-contrast-computed-expected.txt": [ @@ -244129,23 +244188,23 @@ [] ], "color-mix-computed-expected.txt": [ - "e334342b011a7fa1fd28d406105d27416faccaad", + "b9c96909a7c8bf32cd9ca9a974929651a03891fa", [] ], "color-mix-valid-expected.txt": [ - "9a7345f45b02ba4896a4a9790fcae6efb64fd377", + "3d1143afb9aa8978ead0a69ac82f64368319a53e", [] ], "color-valid-expected.txt": [ - "36e511b3edc2a053f51abfe75da15d6095644022", + "f1e4105202864b39ace6e8695bf82c5bf639e457", [] ], "relative-color-computed-expected.txt": [ - "6b9f5f94de3d30775647a10d97273a6246cc7daf", + "a22d69eee728ffebe473dbfb925488fc108c9501", [] ], "relative-color-valid-expected.txt": [ - "feb3805b2a6b0c47c5a2fdc30296d0dbf09c0e9e", + "612ee9bf5ed9112fefd5e982f4f8a4c44f6c7e22", [] ], "system-color-valid-expected.txt": [ @@ -244836,7 +244895,7 @@ "7dde7f870c4d04ff81e8727b5e90aec1f79907de", [] ], - "pseudo-elements-002.tentative-ref.html": [ + "pseudo-elements-002-ref.html": [ "66bddf379d133e6c541c003c8e7a280118b678a4", [] ], @@ -310989,7 +311048,7 @@ [] ], "idlharness.js": [ - "611a26f1fe829afd97cdee7a6f0ff1b5c97422f1", + "53ca06ddf997c2559cf6a88cc994d6919bbf5c2e", [] ], "idlharness.js.headers": [ @@ -315366,7 +315425,7 @@ [] ], "test-utils.js": [ - "88a671b08bf8820685709580e8631b615650721d", + "1c932f17074239f9141aeec0ce90fb065a1f11de", [] ] }, @@ -361074,7 +361133,7 @@ ], "parsing": { "color-computed.html": [ - "6d0a7074f76c086117c5b3a964003aa94f49e814", + "88de9dfe4a7dba96e8716377dfd579803dc479c5", [ null, {} @@ -361102,14 +361161,14 @@ ] ], "color-invalid.html": [ - "a8336fe81b55e0cce779ee44dabe80a48d9e809e", + "0f9a6f414ee4bf262b39ebe3e10b2c924f73c55f", [ null, {} ] ], "color-mix-computed.html": [ - "41ffdcae64c64be6d92d9bd89b12f7f8670f3bdc", + "b7fc240827377b7ccf8009e6d1c6fc407cb90460", [ null, {} @@ -361123,14 +361182,14 @@ ] ], "color-mix-valid.html": [ - "5c66ab1c42973cbc70228de68a098aef94e0ea74", + "d8a32f4ae1243d2bc5888357145e1c7d8e9dbfa6", [ null, {} ] ], "color-valid.html": [ - "bfe2726adf2cf9e3d1ebe07e22aa74aeda9e06df", + "22c6abe7fe5060739435e92721cc45a2dc3ad6eb", [ null, {} @@ -361158,21 +361217,21 @@ ] ], "relative-color-computed.html": [ - "b7eccdba9f45ae0b8d8abb0e242c20be1873187f", + "3c72f569df836e7a6d2a37b987936f10c355b7d0", [ null, {} ] ], "relative-color-invalid.html": [ - "c6f19e1e8b911dec234aeb10f3b3f41b38cd12fb", + "6fbb5aa338d7fce7eb74dfda370981c8f2f686de", [ null, {} ] ], "relative-color-valid.html": [ - "257939633b2ef8ba530baec37ec45e03f459e9b4", + "0788641b3925683cf04d898126edfe59bac78e75", [ null, {} @@ -361432,7 +361491,7 @@ {} ] ], - "container-for-shadow-dom.tentative.html": [ + "container-for-shadow-dom.html": [ "66e9ea088aaa024a3ae3f15da2e69436e7855383", [ null, @@ -361663,7 +361722,7 @@ {} ] ], - "pseudo-elements-003.tentative.html": [ + "pseudo-elements-003.html": [ "7d03dc04b9c5281eb336e8efa36e7973526f9b4d", [ null, @@ -449384,7 +449443,7 @@ }, "processing-model": { "focus-fixup-rule-one-no-dialogs.html": [ - "31b191938402a4c10ef5c42e6dcde2b292695279", + "2413fe266737720d6c3155c4c298d193ae6311fa", [ null, {} @@ -467493,7 +467552,7 @@ }, "inert": { "dynamic-inert-on-focused-element.tentative.html": [ - "42b6e21935b743ac77bd3334d0abf32c8aa7078a", + "0ddf5a995afad3e19f31b9f76ab67e704737355f", [ null, {} @@ -508298,13 +508357,6 @@ } ] ], - "global.html": [ - "08665d318eac889dfba85abd0efeb0a3168913df", - [ - null, - {} - ] - ], "patched-global.any.js": [ "a64a054a97f1f5f133ec961a02f75207b2cb4eee", [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-000.html b/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-000.html new file mode 100644 index 0000000..ae9ee34 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-000.html
@@ -0,0 +1,17 @@ +<!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/#parallel-flows"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:2; column-gap:0; column-fill:auto; width:100px; height:100px; orphans:1; widows:1; background:red;"> + <span> + <!-- First column: --> + <div style="height:50px; background:green;"> + <br> + <!-- Second column: --> + <div style="break-before:column; height:100px; background:green;"></div> + </div> + <!-- First column (the preceding DIV is only 50px tall): --> + <div style="display:inline-block; vertical-align:top; width:100%; height:50px; background:green;"></div> + </span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-001.html b/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-001.html new file mode 100644 index 0000000..de96759 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-001.html
@@ -0,0 +1,15 @@ +<!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/#parallel-flows"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:4; column-gap:0; column-fill:auto; width:100px; height:100px; orphans:1; widows:1; background:red;"> + <span> + <div style="display:inline-block; vertical-align:top; width:100%; height:50px; background:green;"></div> + <div style="height:100px; background:green;"> + <div style="height:150px;"></div> + <div style="height:200px; background:green;"></div> + </div> + <div style="display:inline-block; vertical-align:top; width:100%; height:50px; background:green;"></div> + </span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-002.html b/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-002.html new file mode 100644 index 0000000..c5e44c90 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-002.html
@@ -0,0 +1,15 @@ +<!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/#parallel-flows"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:4; column-gap:0; column-fill:auto; width:100px; height:100px; orphans:1; widows:1; background:red;"> + <span> + <div style="display:inline-block; vertical-align:top; width:100%; height:50px; background:green;"></div> + <div style="height:200px; background:green;"> + <div style="height:250px;"></div> + <div style="height:100px; background:green;"></div> + </div> + <div style="display:inline-block; vertical-align:top; width:100%; height:50px; background:green;"></div> + </span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-003.html b/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-003.html new file mode 100644 index 0000000..a276fde --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-break/block-in-inline-003.html
@@ -0,0 +1,14 @@ +<!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/#parallel-flows"> +<link rel="match" href="../reference/ref-filled-green-100px-square.xht"> +<p>Test passes if there is a filled green square and <strong>no red</strong>.</p> +<div style="columns:4; column-gap:0; column-fill:auto; width:100px; height:100px; orphans:1; widows:1; background:red;"> + <span> + <div style="display:inline-block; vertical-align:top; width:100%; height:50px; background:green;"></div> + <div style="height:50px; background:green;"> + <div style="height:50px;"></div> + <div style="height:300px; background:green;"></div> + </div> + </span> +</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-expected.txt index a9c6646..d290173 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 235 tests; 16 PASS, 219 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 403 tests; 27 PASS, 376 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS Property color value 'currentcolor' PASS Property color value 'transparent' PASS Property color value 'red' @@ -16,6 +16,58 @@ PASS Property color value 'rgb(100, 200, 300)' PASS Property color value 'rgb(20, 10, 0, -10)' PASS Property color value 'rgb(100%, 200%, 300%)' +FAIL Property color value 'rgb(none none none)' assert_true: 'rgb(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(none none none / none)' assert_true: 'rgb(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(128 none none)' assert_true: 'rgb(128 none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(128 none none / none)' assert_true: 'rgb(128 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(none none none / .5)' assert_true: 'rgb(none none none / .5)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(20% none none)' assert_true: 'rgb(20% none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(20% none none / none)' assert_true: 'rgb(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(none none none / 50%)' assert_true: 'rgb(none none none / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none)' assert_true: 'rgba(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none / none)' assert_true: 'rgba(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(128 none none)' assert_true: 'rgba(128 none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(128 none none / none)' assert_true: 'rgba(128 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none / .5)' assert_true: 'rgba(none none none / .5)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(20% none none)' assert_true: 'rgba(20% none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(20% none none / none)' assert_true: 'rgba(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none / 50%)' assert_true: 'rgba(none none none / 50%)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 30% 50%)' +PASS Property color value 'hsl(120 30% 50% / 0.5)' +FAIL Property color value 'hsl(none none none)' assert_true: 'hsl(none none none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(0 0% 0%)' +FAIL Property color value 'hsl(none none none / none)' assert_true: 'hsl(none none none / none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(0 0% 0% / 0)' +FAIL Property color value 'hsla(none none none)' assert_true: 'hsla(none none none)' is a supported value for color. expected true got false +PASS Property color value 'hsla(0 0% 0%)' +FAIL Property color value 'hsla(none none none / none)' assert_true: 'hsla(none none none / none)' is a supported value for color. expected true got false +PASS Property color value 'hsla(0 0% 0% / 0)' +FAIL Property color value 'hsl(120 none none)' assert_true: 'hsl(120 none none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 0% 0%)' +FAIL Property color value 'hsl(120 80% none)' assert_true: 'hsl(120 80% none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 80% 0%)' +FAIL Property color value 'hsl(120 none 50%)' assert_true: 'hsl(120 none 50%)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 0% 50%)' +FAIL Property color value 'hsl(120 100% 50% / none)' assert_true: 'hsl(120 100% 50% / none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 100% 50% / 0)' +FAIL Property color value 'hsl(none 100% 50%)' assert_true: 'hsl(none 100% 50%)' is a supported value for color. expected true got false +PASS Property color value 'hsl(0 100% 50%)' +FAIL Property color value 'hwb(120 30% 50%)' assert_true: 'hwb(120 30% 50%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 30% 50% / 0.5)' assert_true: 'hwb(120 30% 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(none none none)' assert_true: 'hwb(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(0 0% 0%)' assert_true: 'hwb(0 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(none none none / none)' assert_true: 'hwb(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(0 0% 0% / 0)' assert_true: 'hwb(0 0% 0% / 0)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 none none)' assert_true: 'hwb(120 none none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 0% 0%)' assert_true: 'hwb(120 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 80% none)' assert_true: 'hwb(120 80% none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 80% 0%)' assert_true: 'hwb(120 80% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 none 50%)' assert_true: 'hwb(120 none 50%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 0% 50%)' assert_true: 'hwb(120 0% 50%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 30% 50% / none)' assert_true: 'hwb(120 30% 50% / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 30% 50% / 0)' assert_true: 'hwb(120 30% 50% / 0)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(none 100% 50% / none)' assert_true: 'hwb(none 100% 50% / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(0 100% 50% / 0)' assert_true: 'hwb(0 100% 50% / 0)' is a supported value for color. expected true got false FAIL Property color value 'color(srgb 0% 0% 0%)' assert_true: 'color(srgb 0% 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'color(srgb 10% 10% 10%)' assert_true: 'color(srgb 10% 10% 10%)' is a supported value for color. expected true got false FAIL Property color value 'color(srgb .2 .2 25%)' assert_true: 'color(srgb .2 .2 25%)' is a supported value for color. expected true got false @@ -35,6 +87,20 @@ FAIL Property color value 'color(srgb 50% -200 / 0.5)' assert_true: 'color(srgb 50% -200 / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(srgb 50% / 0.5)' assert_true: 'color(srgb 50% / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(srgb / 0.5)' assert_true: 'color(srgb / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200 200 200)' assert_true: 'color(srgb 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200 200 200 / 200)' assert_true: 'color(srgb 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb -200 -200 -200)' assert_true: 'color(srgb -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb -200 -200 -200 / -200)' assert_true: 'color(srgb -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200% 200% 200%)' assert_true: 'color(srgb 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200% 200% 200% / 200%)' assert_true: 'color(srgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb -200% -200% -200% / -200%)' assert_true: 'color(srgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb none none none / none)' assert_true: 'color(srgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb none none none)' assert_true: 'color(srgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 10% none none / none)' assert_true: 'color(srgb 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb none none none / 0.5)' assert_true: 'color(srgb none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0 0 0 / none)' assert_true: 'color(srgb 0 0 0 / none)' is a supported value for color. expected true got false FAIL Property color value 'color(srgb-linear 0% 0% 0%)' assert_true: 'color(srgb-linear 0% 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'color(srgb-linear 10% 10% 10%)' assert_true: 'color(srgb-linear 10% 10% 10%)' is a supported value for color. expected true got false FAIL Property color value 'color(srgb-linear .2 .2 25%)' assert_true: 'color(srgb-linear .2 .2 25%)' is a supported value for color. expected true got false @@ -54,6 +120,20 @@ FAIL Property color value 'color(srgb-linear 50% -200 / 0.5)' assert_true: 'color(srgb-linear 50% -200 / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(srgb-linear 50% / 0.5)' assert_true: 'color(srgb-linear 50% / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(srgb-linear / 0.5)' assert_true: 'color(srgb-linear / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200 200 200)' assert_true: 'color(srgb-linear 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200 200 200 / 200)' assert_true: 'color(srgb-linear 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear -200 -200 -200)' assert_true: 'color(srgb-linear -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear -200 -200 -200 / -200)' assert_true: 'color(srgb-linear -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200% 200% 200%)' assert_true: 'color(srgb-linear 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200% 200% 200% / 200%)' assert_true: 'color(srgb-linear 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear -200% -200% -200% / -200%)' assert_true: 'color(srgb-linear -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear none none none / none)' assert_true: 'color(srgb-linear none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear none none none)' assert_true: 'color(srgb-linear none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 10% none none / none)' assert_true: 'color(srgb-linear 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear none none none / 0.5)' assert_true: 'color(srgb-linear none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0 0 0 / none)' assert_true: 'color(srgb-linear 0 0 0 / none)' is a supported value for color. expected true got false FAIL Property color value 'color(a98-rgb 0% 0% 0%)' assert_true: 'color(a98-rgb 0% 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'color(a98-rgb 10% 10% 10%)' assert_true: 'color(a98-rgb 10% 10% 10%)' is a supported value for color. expected true got false FAIL Property color value 'color(a98-rgb .2 .2 25%)' assert_true: 'color(a98-rgb .2 .2 25%)' is a supported value for color. expected true got false @@ -73,6 +153,20 @@ FAIL Property color value 'color(a98-rgb 50% -200 / 0.5)' assert_true: 'color(a98-rgb 50% -200 / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(a98-rgb 50% / 0.5)' assert_true: 'color(a98-rgb 50% / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(a98-rgb / 0.5)' assert_true: 'color(a98-rgb / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200 200 200)' assert_true: 'color(a98-rgb 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200 200 200 / 200)' assert_true: 'color(a98-rgb 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb -200 -200 -200)' assert_true: 'color(a98-rgb -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb -200 -200 -200 / -200)' assert_true: 'color(a98-rgb -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200% 200% 200%)' assert_true: 'color(a98-rgb 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200% 200% 200% / 200%)' assert_true: 'color(a98-rgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb -200% -200% -200% / -200%)' assert_true: 'color(a98-rgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb none none none / none)' assert_true: 'color(a98-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb none none none)' assert_true: 'color(a98-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 10% none none / none)' assert_true: 'color(a98-rgb 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb none none none / 0.5)' assert_true: 'color(a98-rgb none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0 0 0 / none)' assert_true: 'color(a98-rgb 0 0 0 / none)' is a supported value for color. expected true got false FAIL Property color value 'color(rec2020 0% 0% 0%)' assert_true: 'color(rec2020 0% 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'color(rec2020 10% 10% 10%)' assert_true: 'color(rec2020 10% 10% 10%)' is a supported value for color. expected true got false FAIL Property color value 'color(rec2020 .2 .2 25%)' assert_true: 'color(rec2020 .2 .2 25%)' is a supported value for color. expected true got false @@ -92,6 +186,20 @@ FAIL Property color value 'color(rec2020 50% -200 / 0.5)' assert_true: 'color(rec2020 50% -200 / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(rec2020 50% / 0.5)' assert_true: 'color(rec2020 50% / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(rec2020 / 0.5)' assert_true: 'color(rec2020 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200 200 200)' assert_true: 'color(rec2020 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200 200 200 / 200)' assert_true: 'color(rec2020 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 -200 -200 -200)' assert_true: 'color(rec2020 -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 -200 -200 -200 / -200)' assert_true: 'color(rec2020 -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200% 200% 200%)' assert_true: 'color(rec2020 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200% 200% 200% / 200%)' assert_true: 'color(rec2020 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 -200% -200% -200% / -200%)' assert_true: 'color(rec2020 -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 none none none / none)' assert_true: 'color(rec2020 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 none none none)' assert_true: 'color(rec2020 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 10% none none / none)' assert_true: 'color(rec2020 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 none none none / 0.5)' assert_true: 'color(rec2020 none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0 0 0 / none)' assert_true: 'color(rec2020 0 0 0 / none)' is a supported value for color. expected true got false FAIL Property color value 'color(prophoto-rgb 0% 0% 0%)' assert_true: 'color(prophoto-rgb 0% 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'color(prophoto-rgb 10% 10% 10%)' assert_true: 'color(prophoto-rgb 10% 10% 10%)' is a supported value for color. expected true got false FAIL Property color value 'color(prophoto-rgb .2 .2 25%)' assert_true: 'color(prophoto-rgb .2 .2 25%)' is a supported value for color. expected true got false @@ -111,6 +219,20 @@ FAIL Property color value 'color(prophoto-rgb 50% -200 / 0.5)' assert_true: 'color(prophoto-rgb 50% -200 / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(prophoto-rgb 50% / 0.5)' assert_true: 'color(prophoto-rgb 50% / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(prophoto-rgb / 0.5)' assert_true: 'color(prophoto-rgb / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200 200 200)' assert_true: 'color(prophoto-rgb 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200 200 200 / 200)' assert_true: 'color(prophoto-rgb 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb -200 -200 -200)' assert_true: 'color(prophoto-rgb -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb -200 -200 -200 / -200)' assert_true: 'color(prophoto-rgb -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200% 200% 200%)' assert_true: 'color(prophoto-rgb 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200% 200% 200% / 200%)' assert_true: 'color(prophoto-rgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb -200% -200% -200% / -200%)' assert_true: 'color(prophoto-rgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb none none none / none)' assert_true: 'color(prophoto-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb none none none)' assert_true: 'color(prophoto-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 10% none none / none)' assert_true: 'color(prophoto-rgb 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb none none none / 0.5)' assert_true: 'color(prophoto-rgb none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0 0 0 / none)' assert_true: 'color(prophoto-rgb 0 0 0 / none)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz 0 0 0)' assert_true: 'color(xyz 0 0 0)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz 0 0 0 / 1)' assert_true: 'color(xyz 0 0 0 / 1)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz 1 1 1)' assert_true: 'color(xyz 1 1 1)' is a supported value for color. expected true got false @@ -131,6 +253,12 @@ FAIL Property color value 'color(xyz 1 1 / .5)' assert_true: 'color(xyz 1 1 / .5)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz 1 / 0.5)' assert_true: 'color(xyz 1 / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz / 50%)' assert_true: 'color(xyz / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz none none none / none)' assert_true: 'color(xyz none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz none none none)' assert_true: 'color(xyz none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0.2 none none / none)' assert_true: 'color(xyz 0.2 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz none none none / 0.5)' assert_true: 'color(xyz none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / none)' assert_true: 'color(xyz 0 0 0 / none)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz-d50 0 0 0)' assert_true: 'color(xyz-d50 0 0 0)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz-d50 0 0 0 / 1)' assert_true: 'color(xyz-d50 0 0 0 / 1)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz-d50 1 1 1)' assert_true: 'color(xyz-d50 1 1 1)' is a supported value for color. expected true got false @@ -151,6 +279,12 @@ FAIL Property color value 'color(xyz-d50 1 1 / .5)' assert_true: 'color(xyz-d50 1 1 / .5)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz-d50 1 / 0.5)' assert_true: 'color(xyz-d50 1 / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz-d50 / 50%)' assert_true: 'color(xyz-d50 / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 none none none / none)' assert_true: 'color(xyz-d50 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 none none none)' assert_true: 'color(xyz-d50 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0.2 none none / none)' assert_true: 'color(xyz-d50 0.2 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 none none none / 0.5)' assert_true: 'color(xyz-d50 none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / none)' assert_true: 'color(xyz-d50 0 0 0 / none)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz-d65 0 0 0)' assert_true: 'color(xyz-d65 0 0 0)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz-d65 0 0 0 / 1)' assert_true: 'color(xyz-d65 0 0 0 / 1)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz-d65 1 1 1)' assert_true: 'color(xyz-d65 1 1 1)' is a supported value for color. expected true got false @@ -171,6 +305,12 @@ FAIL Property color value 'color(xyz-d65 1 1 / .5)' assert_true: 'color(xyz-d65 1 1 / .5)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz-d65 1 / 0.5)' assert_true: 'color(xyz-d65 1 / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'color(xyz-d65 / 50%)' assert_true: 'color(xyz-d65 / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 none none none / none)' assert_true: 'color(xyz-d65 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 none none none)' assert_true: 'color(xyz-d65 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0.2 none none / none)' assert_true: 'color(xyz-d65 0.2 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 none none none / 0.5)' assert_true: 'color(xyz-d65 none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / none)' assert_true: 'color(xyz-d65 0 0 0 / none)' is a supported value for color. expected true got false FAIL Property color value 'lab(0% 0 0)' assert_true: 'lab(0% 0 0)' is a supported value for color. expected true got false FAIL Property color value 'lab(0% 0 0 / 1)' assert_true: 'lab(0% 0 0 / 1)' is a supported value for color. expected true got false FAIL Property color value 'lab(0% 0 0 / 0.5)' assert_true: 'lab(0% 0 0 / 0.5)' is a supported value for color. expected true got false @@ -185,6 +325,13 @@ FAIL Property color value 'lab(-40% 0 0)' assert_true: 'lab(-40% 0 0)' is a supported value for color. expected true got false FAIL Property color value 'lab(50% -20 0)' assert_true: 'lab(50% -20 0)' is a supported value for color. expected true got false FAIL Property color value 'lab(50% 0 -20)' assert_true: 'lab(50% 0 -20)' is a supported value for color. expected true got false +FAIL Property color value 'lab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' assert_true: 'lab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'lab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' assert_true: 'lab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'lab(none none none / none)' assert_true: 'lab(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(none none none)' assert_true: 'lab(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(20% none none / none)' assert_true: 'lab(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(none none none / 0.5)' assert_true: 'lab(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / none)' assert_true: 'lab(0% 0 0 / none)' is a supported value for color. expected true got false FAIL Property color value 'oklab(0% 0 0)' assert_true: 'oklab(0% 0 0)' is a supported value for color. expected true got false FAIL Property color value 'oklab(0% 0 0 / 1)' assert_true: 'oklab(0% 0 0 / 1)' is a supported value for color. expected true got false FAIL Property color value 'oklab(0% 0 0 / 0.5)' assert_true: 'oklab(0% 0 0 / 0.5)' is a supported value for color. expected true got false @@ -199,6 +346,13 @@ FAIL Property color value 'oklab(-40% 0 0)' assert_true: 'oklab(-40% 0 0)' is a supported value for color. expected true got false FAIL Property color value 'oklab(50% -20 0)' assert_true: 'oklab(50% -20 0)' is a supported value for color. expected true got false FAIL Property color value 'oklab(50% 0 -20)' assert_true: 'oklab(50% 0 -20)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' assert_true: 'oklab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'oklab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' assert_true: 'oklab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'oklab(none none none / none)' assert_true: 'oklab(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(none none none)' assert_true: 'oklab(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(20% none none / none)' assert_true: 'oklab(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(none none none / 0.5)' assert_true: 'oklab(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / none)' assert_true: 'oklab(0% 0 0 / none)' is a supported value for color. expected true got false FAIL Property color value 'lch(0% 0 0deg)' assert_true: 'lch(0% 0 0deg)' is a supported value for color. expected true got false FAIL Property color value 'lch(0% 0 0deg / 1)' assert_true: 'lch(0% 0 0deg / 1)' is a supported value for color. expected true got false FAIL Property color value 'lch(0% 0 0deg / 0.5)' assert_true: 'lch(0% 0 0deg / 0.5)' is a supported value for color. expected true got false @@ -217,6 +371,13 @@ FAIL Property color value 'lch(0% 0 0 / 0.5)' assert_true: 'lch(0% 0 0 / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'lch(10% 20 20 / 110%)' assert_true: 'lch(10% 20 20 / 110%)' is a supported value for color. expected true got false FAIL Property color value 'lch(10% 20 -700)' assert_true: 'lch(10% 20 -700)' is a supported value for color. expected true got false +FAIL Property color value 'lch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' assert_true: 'lch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'lch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' assert_true: 'lch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'lch(none none none / none)' assert_true: 'lch(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(none none none)' assert_true: 'lch(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(20% none none / none)' assert_true: 'lch(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(none none none / 0.5)' assert_true: 'lch(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lch(0% 0 0 / none)' assert_true: 'lch(0% 0 0 / none)' is a supported value for color. expected true got false FAIL Property color value 'oklch(0% 0 0deg)' assert_true: 'oklch(0% 0 0deg)' is a supported value for color. expected true got false FAIL Property color value 'oklch(0% 0 0deg / 1)' assert_true: 'oklch(0% 0 0deg / 1)' is a supported value for color. expected true got false FAIL Property color value 'oklch(0% 0 0deg / 0.5)' assert_true: 'oklch(0% 0 0deg / 0.5)' is a supported value for color. expected true got false @@ -235,5 +396,12 @@ FAIL Property color value 'oklch(0% 0 0 / 0.5)' assert_true: 'oklch(0% 0 0 / 0.5)' is a supported value for color. expected true got false FAIL Property color value 'oklch(10% 20 20 / 110%)' assert_true: 'oklch(10% 20 20 / 110%)' is a supported value for color. expected true got false FAIL Property color value 'oklch(10% 20 -700)' assert_true: 'oklch(10% 20 -700)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' assert_true: 'oklch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'oklch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' assert_true: 'oklch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'oklch(none none none / none)' assert_true: 'oklch(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(none none none)' assert_true: 'oklch(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(20% none none / none)' assert_true: 'oklch(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(none none none / 0.5)' assert_true: 'oklch(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(0% 0 0 / none)' assert_true: 'oklch(0% 0 0 / none)' is a supported value for color. expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed.html index 6d0a707..88de9df 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed.html +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-computed.html
@@ -38,26 +38,96 @@ test_computed_value("color", "rgb(20, 10, 0, -10)", "rgba(20, 10, 0, 0)"); test_computed_value("color", "rgb(100%, 200%, 300%)", "rgb(255, 255, 255)"); +test_computed_value("color", "rgb(none none none)", "rgb(0, 0, 0)"); +test_computed_value("color", "rgb(none none none / none)", "rgba(0, 0, 0, 0)"); +test_computed_value("color", "rgb(128 none none)", "rgb(128, 0, 0)"); +test_computed_value("color", "rgb(128 none none / none)", "rgba(128, 0, 0, 0)"); +test_computed_value("color", "rgb(none none none / .5)", "rgba(0, 0, 0, 0.5)"); +test_computed_value("color", "rgb(20% none none)", "rgb(51, 0, 0)"); +test_computed_value("color", "rgb(20% none none / none)", "rgba(51, 0, 0, 0)"); +test_computed_value("color", "rgb(none none none / 50%)", "rgba(0, 0, 0, 0.5)"); +test_computed_value("color", "rgba(none none none)", "rgb(0, 0, 0)"); +test_computed_value("color", "rgba(none none none / none)", "rgba(0, 0, 0, 0)"); +test_computed_value("color", "rgba(128 none none)", "rgb(128, 0, 0)"); +test_computed_value("color", "rgba(128 none none / none)", "rgba(128, 0, 0, 0)"); +test_computed_value("color", "rgba(none none none / .5)", "rgba(0, 0, 0, 0.5)"); +test_computed_value("color", "rgba(20% none none)", "rgb(51, 0, 0)"); +test_computed_value("color", "rgba(20% none none / none)", "rgba(51, 0, 0, 0)"); +test_computed_value("color", "rgba(none none none / 50%)", "rgba(0, 0, 0, 0.5)"); + +test_computed_value("color", "hsl(120 30% 50%)", "rgb(89, 166, 89)"); +test_computed_value("color", "hsl(120 30% 50% / 0.5)", "rgba(89, 166, 89, 0.5)"); +test_computed_value("color", "hsl(none none none)", "rgb(0, 0, 0)"); +test_computed_value("color", "hsl(0 0% 0%)", "rgb(0, 0, 0)"); +test_computed_value("color", "hsl(none none none / none)", "rgba(0, 0, 0, 0)"); +test_computed_value("color", "hsl(0 0% 0% / 0)", "rgba(0, 0, 0, 0)"); +test_computed_value("color", "hsla(none none none)", "rgb(0, 0, 0)"); +test_computed_value("color", "hsla(0 0% 0%)", "rgb(0, 0, 0)"); +test_computed_value("color", "hsla(none none none / none)", "rgba(0, 0, 0, 0)"); +test_computed_value("color", "hsla(0 0% 0% / 0)", "rgba(0, 0, 0, 0)"); +test_computed_value("color", "hsl(120 none none)", "rgb(0, 0, 0)"); +test_computed_value("color", "hsl(120 0% 0%)", "rgb(0, 0, 0)"); +test_computed_value("color", "hsl(120 80% none)", "rgb(0, 0, 0)"); +test_computed_value("color", "hsl(120 80% 0%)", "rgb(0, 0, 0)"); +test_computed_value("color", "hsl(120 none 50%)", "rgb(128, 128, 128)"); +test_computed_value("color", "hsl(120 0% 50%)", "rgb(128, 128, 128)"); +test_computed_value("color", "hsl(120 100% 50% / none)", "rgba(0, 255, 0, 0)"); +test_computed_value("color", "hsl(120 100% 50% / 0)", "rgba(0, 255, 0, 0)"); +test_computed_value("color", "hsl(none 100% 50%)", "rgb(255, 0, 0)"); +test_computed_value("color", "hsl(0 100% 50%)", "rgb(255, 0, 0)"); + +test_computed_value("color", "hwb(120 30% 50%)", "rgb(77, 128, 77)"); +test_computed_value("color", "hwb(120 30% 50% / 0.5)", "rgba(77, 128, 77, 0.5)"); +test_computed_value("color", "hwb(none none none)", "rgb(255, 0, 0)"); +test_computed_value("color", "hwb(0 0% 0%)", "rgb(255, 0, 0)"); +test_computed_value("color", "hwb(none none none / none)", "rgba(255, 0, 0, 0)"); +test_computed_value("color", "hwb(0 0% 0% / 0)", "rgba(255, 0, 0, 0)"); +test_computed_value("color", "hwb(120 none none)", "rgb(0, 255, 0)"); +test_computed_value("color", "hwb(120 0% 0%)", "rgb(0, 255, 0)"); +test_computed_value("color", "hwb(120 80% none)", "rgb(204, 255, 204)"); +test_computed_value("color", "hwb(120 80% 0%)", "rgb(204, 255, 204)"); +test_computed_value("color", "hwb(120 none 50%)", "rgb(0, 128, 0)"); +test_computed_value("color", "hwb(120 0% 50%)", "rgb(0, 128, 0)"); +test_computed_value("color", "hwb(120 30% 50% / none)", "rgba(77, 128, 77, 0)"); +test_computed_value("color", "hwb(120 30% 50% / 0)", "rgba(77, 128, 77, 0)"); +test_computed_value("color", "hwb(none 100% 50% / none)", "rgba(170, 170, 170, 0)"); +test_computed_value("color", "hwb(0 100% 50% / 0)", "rgba(170, 170, 170, 0)"); + for (const colorSpace of [ "srgb", "srgb-linear", "a98-rgb", "rec2020", "prophoto-rgb" ]) { test_computed_value("color", `color(${colorSpace} 0% 0% 0%)`, `color(${colorSpace} 0 0 0)`); test_computed_value("color", `color(${colorSpace} 10% 10% 10%)`, `color(${colorSpace} 0.1 0.1 0.1)`); test_computed_value("color", `color(${colorSpace} .2 .2 25%)`, `color(${colorSpace} 0.2 0.2 0.25)`); test_computed_value("color", `color(${colorSpace} 0 0 0 / 1)`, `color(${colorSpace} 0 0 0)`); test_computed_value("color", `color(${colorSpace} 0% 0 0 / 0.5)`, `color(${colorSpace} 0 0 0 / 0.5)`); - test_computed_value("color", `color(${colorSpace} 20% 0 10/0.5)`, `color(${colorSpace} 0.2 0 1 / 0.5)`); - test_computed_value("color", `color(${colorSpace} 20% 0 10/50%)`, `color(${colorSpace} 0.2 0 1 / 0.5)`); - test_computed_value("color", `color(${colorSpace} 400% 0 10/50%)`, `color(${colorSpace} 1 0 1 / 0.5)`); - test_computed_value("color", `color(${colorSpace} 50% -160 160)`, `color(${colorSpace} 0.5 0 1)`); - test_computed_value("color", `color(${colorSpace} 50% -200 200)`, `color(${colorSpace} 0.5 0 1)`); + test_computed_value("color", `color(${colorSpace} 20% 0 10/0.5)`, `color(${colorSpace} 0.2 0 10 / 0.5)`); + test_computed_value("color", `color(${colorSpace} 20% 0 10/50%)`, `color(${colorSpace} 0.2 0 10 / 0.5)`); + test_computed_value("color", `color(${colorSpace} 400% 0 10/50%)`, `color(${colorSpace} 4 0 10 / 0.5)`); + test_computed_value("color", `color(${colorSpace} 50% -160 160)`, `color(${colorSpace} 0.5 -160 160)`); + test_computed_value("color", `color(${colorSpace} 50% -200 200)`, `color(${colorSpace} 0.5 -200 200)`); test_computed_value("color", `color(${colorSpace} 0 0 0 / -10%)`, `color(${colorSpace} 0 0 0 / 0)`); test_computed_value("color", `color(${colorSpace} 0 0 0 / 110%)`, `color(${colorSpace} 0 0 0)`); test_computed_value("color", `color(${colorSpace} 0 0 0 / 300%)`, `color(${colorSpace} 0 0 0)`); - test_computed_value("color", `color(${colorSpace} 50% -200)`, `color(${colorSpace} 0.5 0 0)`); + test_computed_value("color", `color(${colorSpace} 50% -200)`, `color(${colorSpace} 0.5 -200 0)`); test_computed_value("color", `color(${colorSpace} 50%)`, `color(${colorSpace} 0.5 0 0)`); test_computed_value("color", `color(${colorSpace})`, `color(${colorSpace} 0 0 0)`); - test_computed_value("color", `color(${colorSpace} 50% -200 / 0.5)`, `color(${colorSpace} 0.5 0 0 / 0.5)`); + test_computed_value("color", `color(${colorSpace} 50% -200 / 0.5)`, `color(${colorSpace} 0.5 -200 0 / 0.5)`); test_computed_value("color", `color(${colorSpace} 50% / 0.5)`, `color(${colorSpace} 0.5 0 0 / 0.5)`); test_computed_value("color", `color(${colorSpace} / 0.5)`, `color(${colorSpace} 0 0 0 / 0.5)`); + test_computed_value("color", `color(${colorSpace} 200 200 200)`, `color(${colorSpace} 200 200 200)`); + test_computed_value("color", `color(${colorSpace} 200 200 200 / 200)`, `color(${colorSpace} 200 200 200)`); + test_computed_value("color", `color(${colorSpace} -200 -200 -200)`, `color(${colorSpace} -200 -200 -200)`); + test_computed_value("color", `color(${colorSpace} -200 -200 -200 / -200)`, `color(${colorSpace} -200 -200 -200 / 0)`); + test_computed_value("color", `color(${colorSpace} 200% 200% 200%)`, `color(${colorSpace} 2 2 2)`); + test_computed_value("color", `color(${colorSpace} 200% 200% 200% / 200%)`, `color(${colorSpace} 2 2 2)`); + test_computed_value("color", `color(${colorSpace} -200% -200% -200% / -200%)`, `color(${colorSpace} -2 -2 -2 / 0)`); + test_computed_value("color", `color(${colorSpace} calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))`, `color(${colorSpace} 1.5 -0.5 0.5 / 0.5)`); + test_computed_value("color", `color(${colorSpace} calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))`, `color(${colorSpace} 1.5 -0.5 0.5 / 0)`); + + test_computed_value("color", `color(${colorSpace} none none none / none)`, `color(${colorSpace} none none none / none)`); + test_computed_value("color", `color(${colorSpace} none none none)`, `color(${colorSpace} none none none)`); + test_computed_value("color", `color(${colorSpace} 10% none none / none)`, `color(${colorSpace} 0.1 none none / none)`); + test_computed_value("color", `color(${colorSpace} none none none / 0.5)`, `color(${colorSpace} none none none / 0.5)`); + test_computed_value("color", `color(${colorSpace} 0 0 0 / none)`, `color(${colorSpace} 0 0 0 / none)`); } for (const colorSpace of [ "xyz", "xyz-d50", "xyz-d65" ]) { @@ -83,6 +153,13 @@ test_computed_value("color", `color(${colorSpace} 1 1 / .5)`, `color(${resultColorSpace} 1 1 0 / 0.5)`); test_computed_value("color", `color(${colorSpace} 1 / 0.5)`, `color(${resultColorSpace} 1 0 0 / 0.5)`); test_computed_value("color", `color(${colorSpace} / 50%)`, `color(${resultColorSpace} 0 0 0 / 0.5)`); + test_computed_value("color", `color(${colorSpace} calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))`, `color(${resultColorSpace} 1.5 -0.5 0.5 / 0.5)`); + + test_computed_value("color", `color(${colorSpace} none none none / none)`, `color(${resultColorSpace} none none none / none)`); + test_computed_value("color", `color(${colorSpace} none none none)`, `color(${resultColorSpace} none none none)`); + test_computed_value("color", `color(${colorSpace} 0.2 none none / none)`, `color(${resultColorSpace} 0.2 none none / none)`); + test_computed_value("color", `color(${colorSpace} none none none / 0.5)`, `color(${resultColorSpace} none none none / 0.5)`); + test_computed_value("color", `color(${colorSpace} 0 0 0 / none)`, `color(${resultColorSpace} 0 0 0 / none)`); } for (const colorSpace of [ "lab", "oklab" ]) { @@ -100,6 +177,14 @@ test_computed_value("color", `${colorSpace}(-40% 0 0)`, `${colorSpace}(0% 0 0)`); test_computed_value("color", `${colorSpace}(50% -20 0)`, `${colorSpace}(50% -20 0)`); test_computed_value("color", `${colorSpace}(50% 0 -20)`, `${colorSpace}(50% 0 -20)`); + test_computed_value("color", `${colorSpace}(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))`, `${colorSpace}(150% -0.5 1.5 / 0.5)`); + test_computed_value("color", `${colorSpace}(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))`, `${colorSpace}(0% 1.5 -1.5 / 0)`); + + test_computed_value("color", `${colorSpace}(none none none / none)`, `${colorSpace}(none none none / none)`); + test_computed_value("color", `${colorSpace}(none none none)`, `${colorSpace}(none none none)`); + test_computed_value("color", `${colorSpace}(20% none none / none)`, `${colorSpace}(20% none none / none)`); + test_computed_value("color", `${colorSpace}(none none none / 0.5)`, `${colorSpace}(none none none / 0.5)`); + test_computed_value("color", `${colorSpace}(0% 0 0 / none)`, `${colorSpace}(0% 0 0 / none)`); } for (const colorSpace of [ "lch", "oklch" ]) { @@ -121,6 +206,14 @@ test_computed_value("color", `${colorSpace}(0% 0 0 / 0.5)`, `${colorSpace}(0% 0 0 / 0.5)`); test_computed_value("color", `${colorSpace}(10% 20 20 / 110%)`, `${colorSpace}(10% 20 20)`); test_computed_value("color", `${colorSpace}(10% 20 -700)`, `${colorSpace}(10% 20 20)`); + test_computed_value("color", `${colorSpace}(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))`, `${colorSpace}(150% 0 40 / 0.5)`); + test_computed_value("color", `${colorSpace}(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))`, `${colorSpace}(0% 1.5 320 / 0)`); + + test_computed_value("color", `${colorSpace}(none none none / none)`, `${colorSpace}(none none none / none)`); + test_computed_value("color", `${colorSpace}(none none none)`, `${colorSpace}(none none none)`); + test_computed_value("color", `${colorSpace}(20% none none / none)`, `${colorSpace}(20% none none / none)`); + test_computed_value("color", `${colorSpace}(none none none / 0.5)`, `${colorSpace}(none none none / 0.5)`); + test_computed_value("color", `${colorSpace}(0% 0 0 / none)`, `${colorSpace}(0% 0 0 / none)`); } </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-invalid.html index a8336fe8..0f9a6f4 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-invalid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-invalid.html
@@ -22,6 +22,14 @@ test_invalid_value("color", "hsla(1,2,3,4,5)"); test_invalid_value("color", "rgb(10%, 20, 30%)"); test_invalid_value("color", "rgba(-2, 300, 400%, -0.5)"); +test_invalid_value("color", "rgb(none, none, none)"); +test_invalid_value("color", "rgba(none, none, none, none)"); +test_invalid_value("color", "rgb(128, 0, none)"); +test_invalid_value("color", "rgb(255, 255, 255, none)"); +test_invalid_value("color", "hsl(none, none, none)"); +test_invalid_value("color", "hsla(none, none, none, none)"); +test_invalid_value("color", "hsl(none, 100%, 50%)"); +test_invalid_value("color", "hsla(120, 100%, 50%, none)"); for (const colorSpace of [ "srgb", "srgb-linear", "a98-rgb", "rec2020", "prophoto-rgb" ]) { test_invalid_value("color", `color(${colorSpace} 0 0 0 0)`);
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-computed-expected.txt index e334342..b9c96909 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-computed-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-computed-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 342 tests; 0 PASS, 342 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 474 tests; 0 PASS, 474 FAIL, 0 TIMEOUT, 0 NOTRUN. FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))' is a supported value for color. expected true got false @@ -54,6 +54,24 @@ FAIL Property color value 'color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(none none none), hsl(none none none))' assert_true: 'color-mix(in hsl, hsl(none none none), hsl(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))' assert_true: 'color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))' assert_true: 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))' assert_true: 'color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))' assert_true: 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))' assert_true: 'color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))' is a supported value for color. expected true got false @@ -108,6 +126,24 @@ FAIL Property color value 'color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(none none none), hwb(none none none))' assert_true: 'color-mix(in hwb, hwb(none none none), hwb(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))' assert_true: 'color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in lch, 25% lch(10% 20 30deg), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, 25% lch(10% 20 30deg), lch(50% 60 70deg))' is a supported value for color. expected true got false @@ -162,6 +198,15 @@ FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(none none none), lch(none none none))' assert_true: 'color-mix(in lch, lch(none none none), lch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(none none none), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(none none none), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(none none none))' assert_true: 'color-mix(in lch, lch(10% 20 30deg), lch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 none), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 none), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 none))' assert_true: 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(none 20 30deg), lch(50% none 70deg))' assert_true: 'color-mix(in lch, lch(none 20 30deg), lch(50% none 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / 0.5))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / none))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / none))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in oklch, 25% oklch(10% 20 30deg), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, 25% oklch(10% 20 30deg), oklch(50% 60 70deg))' is a supported value for color. expected true got false @@ -216,6 +261,15 @@ FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(none none none), oklch(none none none))' assert_true: 'color-mix(in oklch, oklch(none none none), oklch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(none none none), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(none none none), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(none none none))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), oklch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 none), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 none), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 none))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(none 20 30deg), oklch(50% none 70deg))' assert_true: 'color-mix(in oklch, oklch(none 20 30deg), oklch(50% none 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / 0.5))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / none))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / none))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in lab, lab(10% 20 30), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30), lab(50% 60 70))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in lab, 25% lab(10% 20 30), lab(50% 60 70))' assert_true: 'color-mix(in lab, 25% lab(10% 20 30), lab(50% 60 70))' is a supported value for color. expected true got false @@ -234,6 +288,15 @@ FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 30%, lab(50% 60 70 / .8) 90%)' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 30%, lab(50% 60 70 / .8) 90%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(none none none), lab(none none none))' assert_true: 'color-mix(in lab, lab(none none none), lab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(none none none), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(none none none), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), lab(none none none))' assert_true: 'color-mix(in lab, lab(10% 20 30), lab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 none), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 none), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), lab(50% 60 none))' assert_true: 'color-mix(in lab, lab(10% 20 30), lab(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(none 20 30), lab(50% none 70))' assert_true: 'color-mix(in lab, lab(none 20 30), lab(50% none 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / 0.5))' assert_true: 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / none))' assert_true: 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / none))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in oklab, 25% oklab(10% 20 30), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, 25% oklab(10% 20 30), oklab(50% 60 70))' is a supported value for color. expected true got false @@ -252,6 +315,15 @@ FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 30%, oklab(50% 60 70 / .8) 90%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 30%, oklab(50% 60 70 / .8) 90%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 12.5%, oklab(50% 60 70 / .8) 37.5%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 12.5%, oklab(50% 60 70 / .8) 37.5%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 0%, oklab(50% 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 0%, oklab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(none none none), oklab(none none none))' assert_true: 'color-mix(in oklab, oklab(none none none), oklab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(none none none), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(none none none), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(none none none))' assert_true: 'color-mix(in oklab, oklab(10% 20 30), oklab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 none), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 none), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 none))' assert_true: 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(none 20 30), oklab(50% none 70))' assert_true: 'color-mix(in oklab, oklab(none 20 30), oklab(50% none 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / 0.5))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / none))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / none))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))' is a supported value for color. expected true got false @@ -270,6 +342,18 @@ FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))' assert_true: 'color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))' assert_true: 'color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))' assert_true: 'color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb none none none))' assert_true: 'color-mix(in srgb, color(srgb none none none), color(srgb none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))' assert_true: 'color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false @@ -288,6 +372,18 @@ FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz, 25% color(xyz .1 .2 .3), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, 25% color(xyz .1 .2 .3), color(xyz .5 .6 .7))' is a supported value for color. expected true got false @@ -306,6 +402,18 @@ FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))' assert_true: 'color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))' assert_true: 'color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz none none none))' assert_true: 'color-mix(in xyz, color(xyz none none none), color(xyz none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))' assert_true: 'color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false @@ -324,6 +432,18 @@ FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false @@ -342,5 +462,17 @@ FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))' is a supported value for color. expected true got false Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-computed.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-computed.html index 41ffdca..b7fc240 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-computed.html +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-computed.html
@@ -86,6 +86,28 @@ test_computed_value(`color`, `color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))`, canonicalize(`hsl(170deg 50% 50%)`)); test_computed_value(`color`, `color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))`, canonicalize(`hsl(170deg 50% 50%)`)); + test_computed_value(`color`, `color-mix(in hsl, hsl(none none none), hsl(none none none))`, canonicalize(`hsl(none none none)`)); + test_computed_value(`color`, `color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))`, canonicalize(`hsl(30deg 40% 80%)`)); + test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))`, canonicalize(`hsl(120deg 20% 40%)`)); + test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))`, canonicalize(`hsl(75deg 30% 60%)`)); + test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))`, canonicalize(`hsl(75deg 20% 40%)`)); + test_computed_value(`color`, `color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))`, canonicalize(`hsl(30deg 20% 60%)`)); + + test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))`, canonicalize(`hsl(60deg 40% 40%)`)); + test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))`, canonicalize(`hsl(60deg 40% 40% / 0.5)`)); + test_computed_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))`, canonicalize(`hsl(60deg 40% 40% / none)`)); + + test_computed_value(`color`, `color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0). + test_computed_value(`color`, `color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_computed_value(`color`, `color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_computed_value(`color`, `color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_computed_value(`color`, `color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_computed_value(`color`, `color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255). + test_computed_value(`color`, `color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24). + test_computed_value(`color`, `color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255). + test_computed_value(`color`, `color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24). + + test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(147, 179, 52)`); test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`); test_computed_value(`color`, `color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`); @@ -148,6 +170,26 @@ test_computed_value(`color`, `color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))`, canonicalize(`hwb(170deg 30% 40%)`)); test_computed_value(`color`, `color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))`, canonicalize(`hwb(170deg 30% 40%)`)); + test_computed_value(`color`, `color-mix(in hwb, hwb(none none none), hwb(none none none))`, canonicalize(`hwb(none none none)`)); + test_computed_value(`color`, `color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))`, canonicalize(`hwb(30deg 30% 40%)`)); + test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))`, canonicalize(`hwb(120deg 10% 20%)`)); + test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))`, canonicalize(`hwb(75deg 20% 40%)`)); + test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))`, canonicalize(`hwb(75deg 20% 20%)`)); + test_computed_value(`color`, `color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))`, canonicalize(`hwb(30deg 10% 30%)`)); + test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))`, canonicalize(`hwb(75deg 20% 30%)`)); + test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))`, canonicalize(`hwb(75deg 20% 30% / 0.5)`)); + test_computed_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))`, canonicalize(`hwb(75deg 20% 30% / none)`)); + + test_computed_value(`color`, `color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0). + test_computed_value(`color`, `color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_computed_value(`color`, `color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_computed_value(`color`, `color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_computed_value(`color`, `color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_computed_value(`color`, `color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255). + test_computed_value(`color`, `color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24). + test_computed_value(`color`, `color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255). + test_computed_value(`color`, `color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24). + for (const colorSpace of [ "lch", "oklch" ]) { test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 50)`); test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg) 25%, ${colorSpace}(50% 60 70deg))`, `${colorSpace}(40% 50 60)`); @@ -210,6 +252,16 @@ test_computed_value(`color`, `color-mix(in ${colorSpace} specified hue, ${colorSpace}(100% 0 330deg), ${colorSpace}(100% 0 50deg))`, `${colorSpace}(100% 0 190)`); test_computed_value(`color`, `color-mix(in ${colorSpace} specified hue, ${colorSpace}(100% 0 20deg), ${colorSpace}(100% 0 320deg))`, `${colorSpace}(100% 0 170)`); test_computed_value(`color`, `color-mix(in ${colorSpace} specified hue, ${colorSpace}(100% 0 320deg), ${colorSpace}(100% 0 20deg))`, `${colorSpace}(100% 0 170)`); + + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(none none none))`, `${colorSpace}(none none none)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(50% 60 70)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(none none none))`, `${colorSpace}(10% 20 30)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 70)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(50% 60 none))`, `${colorSpace}(30% 40 30)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none 20 30deg), ${colorSpace}(50% none 70deg))`, `${colorSpace}(50% 20 50)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 50)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg / 0.5))`, `${colorSpace}(30% 40 50 / 0.5)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg / none))`, `${colorSpace}(30% 40 50 / none)`); } for (const colorSpace of [ "lab", "oklab" ]) { @@ -232,6 +284,16 @@ test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / .4) 30%, ${colorSpace}(50% 60 70 / .8) 90%)`, `${colorSpace}(44.285713% 54.285717 64.28571 / 0.7)`); // Scale down > 100% sum. test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / .4) 12.5%, ${colorSpace}(50% 60 70 / .8) 37.5%)`, `${colorSpace}(44.285713% 54.285717 64.28571 / 0.35)`); // Scale up < 100% sum, causes alpha multiplication. test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / .4) 0%, ${colorSpace}(50% 60 70 / .8))`, `${colorSpace}(50% 60 70 / 0.8)`); + + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(none none none))`, `${colorSpace}(none none none)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(50% 60 70))`, `${colorSpace}(50% 60 70)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30), ${colorSpace}(none none none))`, `${colorSpace}(10% 20 30)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 none), ${colorSpace}(50% 60 70))`, `${colorSpace}(30% 40 70)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30), ${colorSpace}(50% 60 none))`, `${colorSpace}(30% 40 30)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none 20 30), ${colorSpace}(50% none 70))`, `${colorSpace}(50% 20 50)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70))`, `${colorSpace}(30% 40 50)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70 / 0.5))`, `${colorSpace}(30% 40 50 / 0.5)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70 / none))`, `${colorSpace}(30% 40 50 / none)`); } for (const colorSpace of [ "srgb", "srgb-linear", "xyz", "xyz-d50", "xyz-d65" ]) { @@ -256,6 +318,20 @@ test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / .4) 30%, color(${colorSpace} .5 .6 .7 / .8) 90%)`, `color(${resultColorSpace} 0.44285715 0.54285717 0.64285713 / 0.7)`); // Scale down > 100% sum. test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / .4) 12.5%, color(${colorSpace} .5 .6 .7 / .8) 37.5%)`, `color(${resultColorSpace} 0.44285715 0.54285717 0.64285713 / 0.35)`); // Scale up < 100% sum, causes alpha multiplication. test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / .4) 0%, color(${colorSpace} .5 .6 .7 / .8))`, `color(${resultColorSpace} 0.5 0.6 0.7 / 0.8)`); + + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} 2 3 4 / 5), color(${colorSpace} 4 6 8 / 10))`, `color(${resultColorSpace} 3 4.5 6)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} -2 -3 -4), color(${colorSpace} -4 -6 -8))`, `color(${resultColorSpace} -3 -4.5 -6)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} -2 -3 -4 / -5), color(${colorSpace} -4 -6 -8 / -10))`, `color(${resultColorSpace} 0 0 0 / 0)`); + + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none none none), color(${colorSpace} none none none))`, `color(${resultColorSpace} none none none)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none none none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.5 0.6 0.7)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3), color(${colorSpace} none none none))`, `color(${resultColorSpace} 0.1 0.2 0.3)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.3 0.4 0.7)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3), color(${colorSpace} .5 .6 none))`, `color(${resultColorSpace} 0.3 0.4 0.3)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none .2 .3), color(${colorSpace} .5 none .7))`, `color(${resultColorSpace} 0.5 0.2 0.5)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.3 0.4 0.5)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7 / 0.5))`, `color(${resultColorSpace} 0.3 0.4 0.5 / 0.5)`); + test_computed_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7 / none))`, `color(${resultColorSpace} 0.3 0.4 0.5 / none)`); } </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-valid-expected.txt index 9a7345f..3d1143a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-valid-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-valid-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 342 tests; 0 PASS, 342 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 474 tests; 0 PASS, 474 FAIL, 0 TIMEOUT, 0 NOTRUN. FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -54,6 +54,24 @@ FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(none none none), hsl(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -108,6 +126,24 @@ FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(none none none), hwb(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in lch, 25% lch(10% 20 30deg), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -162,6 +198,15 @@ FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(none none none), lch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(none none none), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 none), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(none 20 30deg), lch(50% none 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / none))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in oklch, 25% oklch(10% 20 30deg), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -216,6 +261,15 @@ FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(none none none), oklch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(none none none), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 none), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(none 20 30deg), oklch(50% none 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / none))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in lab, 25% lab(10% 20 30), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -234,6 +288,15 @@ FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 30%, lab(50% 60 70 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(none none none), lab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(none none none), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 none), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(none 20 30), lab(50% none 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in oklab, 25% oklab(10% 20 30), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -252,6 +315,15 @@ FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 30%, oklab(50% 60 70 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 12.5%, oklab(50% 60 70 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 0%, oklab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(none none none), oklab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(none none none), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 none), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(none 20 30), oklab(50% none 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -270,6 +342,18 @@ FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb none none none), color(srgb none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -288,6 +372,18 @@ FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz, 25% color(xyz .1 .2 .3), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -306,6 +402,18 @@ FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz none none none), color(xyz none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -324,6 +432,18 @@ FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -342,5 +462,17 @@ FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-valid.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-valid.html index 5c66ab1..d8a32f4a 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-valid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-mix-valid.html
@@ -86,6 +86,28 @@ test_valid_value(`color`, `color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))`, canonicalize(`hsl(170deg 50% 50%)`)); test_valid_value(`color`, `color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))`, canonicalize(`hsl(170deg 50% 50%)`)); + test_valid_value(`color`, `color-mix(in hsl, hsl(none none none), hsl(none none none))`, canonicalize(`hsl(none none none)`)); + test_valid_value(`color`, `color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))`, canonicalize(`hsl(30deg 40% 80%)`)); + test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))`, canonicalize(`hsl(120deg 20% 40%)`)); + test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))`, canonicalize(`hsl(75deg 30% 60%)`)); + test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))`, canonicalize(`hsl(75deg 20% 40%)`)); + test_valid_value(`color`, `color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))`, canonicalize(`hsl(30deg 20% 60%)`)); + + test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))`, canonicalize(`hsl(60deg 40% 40%)`)); + test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))`, canonicalize(`hsl(60deg 40% 40% / 0.5)`)); + test_valid_value(`color`, `color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))`, canonicalize(`hsl(60deg 40% 40% / none)`)); + + test_valid_value(`color`, `color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0). + test_valid_value(`color`, `color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_valid_value(`color`, `color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_valid_value(`color`, `color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_valid_value(`color`, `color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_valid_value(`color`, `color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255). + test_valid_value(`color`, `color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24). + test_valid_value(`color`, `color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255). + test_valid_value(`color`, `color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24). + + test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(147, 179, 52)`); test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`); test_valid_value(`color`, `color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))`, `rgb(166, 153, 64)`); @@ -148,6 +170,26 @@ test_valid_value(`color`, `color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))`, canonicalize(`hwb(170deg 30% 40%)`)); test_valid_value(`color`, `color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))`, canonicalize(`hwb(170deg 30% 40%)`)); + test_valid_value(`color`, `color-mix(in hwb, hwb(none none none), hwb(none none none))`, canonicalize(`hwb(none none none)`)); + test_valid_value(`color`, `color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))`, canonicalize(`hwb(30deg 30% 40%)`)); + test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))`, canonicalize(`hwb(120deg 10% 20%)`)); + test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))`, canonicalize(`hwb(75deg 20% 40%)`)); + test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))`, canonicalize(`hwb(75deg 20% 20%)`)); + test_valid_value(`color`, `color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))`, canonicalize(`hwb(30deg 10% 30%)`)); + test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))`, canonicalize(`hwb(75deg 20% 30%)`)); + test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))`, canonicalize(`hwb(75deg 20% 30% / 0.5)`)); + test_valid_value(`color`, `color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))`, canonicalize(`hwb(75deg 20% 30% / none)`)); + + test_valid_value(`color`, `color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0). + test_valid_value(`color`, `color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_valid_value(`color`, `color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_valid_value(`color`, `color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_valid_value(`color`, `color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_valid_value(`color`, `color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255). + test_valid_value(`color`, `color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24). + test_valid_value(`color`, `color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255). + test_valid_value(`color`, `color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24). + for (const colorSpace of [ "lch", "oklch" ]) { test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 50)`); test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg) 25%, ${colorSpace}(50% 60 70deg))`, `${colorSpace}(40% 50 60)`); @@ -210,6 +252,16 @@ test_valid_value(`color`, `color-mix(in ${colorSpace} specified hue, ${colorSpace}(100% 0 330deg), ${colorSpace}(100% 0 50deg))`, `${colorSpace}(100% 0 190)`); test_valid_value(`color`, `color-mix(in ${colorSpace} specified hue, ${colorSpace}(100% 0 20deg), ${colorSpace}(100% 0 320deg))`, `${colorSpace}(100% 0 170)`); test_valid_value(`color`, `color-mix(in ${colorSpace} specified hue, ${colorSpace}(100% 0 320deg), ${colorSpace}(100% 0 20deg))`, `${colorSpace}(100% 0 170)`); + + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(none none none))`, `${colorSpace}(none none none)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(50% 60 70)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(none none none))`, `${colorSpace}(10% 20 30)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 70)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg), ${colorSpace}(50% 60 none))`, `${colorSpace}(30% 40 30)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none 20 30deg), ${colorSpace}(50% none 70deg))`, `${colorSpace}(50% 20 50)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg))`, `${colorSpace}(30% 40 50)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg / 0.5))`, `${colorSpace}(30% 40 50 / 0.5)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30deg / none), ${colorSpace}(50% 60 70deg / none))`, `${colorSpace}(30% 40 50 / none)`); } for (const colorSpace of [ "lab", "oklab" ]) { @@ -232,6 +284,16 @@ test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / .4) 30%, ${colorSpace}(50% 60 70 / .8) 90%)`, `${colorSpace}(44.285713% 54.285717 64.28571 / 0.7)`); // Scale down > 100% sum. test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / .4) 12.5%, ${colorSpace}(50% 60 70 / .8) 37.5%)`, `${colorSpace}(44.285713% 54.285717 64.28571 / 0.35)`); // Scale up < 100% sum, causes alpha multiplication. test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / .4) 0%, ${colorSpace}(50% 60 70 / .8))`, `${colorSpace}(50% 60 70 / 0.8)`); + + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(none none none))`, `${colorSpace}(none none none)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none none none), ${colorSpace}(50% 60 70))`, `${colorSpace}(50% 60 70)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30), ${colorSpace}(none none none))`, `${colorSpace}(10% 20 30)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 none), ${colorSpace}(50% 60 70))`, `${colorSpace}(30% 40 70)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30), ${colorSpace}(50% 60 none))`, `${colorSpace}(30% 40 30)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(none 20 30), ${colorSpace}(50% none 70))`, `${colorSpace}(50% 20 50)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70))`, `${colorSpace}(30% 40 50)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70 / 0.5))`, `${colorSpace}(30% 40 50 / 0.5)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, ${colorSpace}(10% 20 30 / none), ${colorSpace}(50% 60 70 / none))`, `${colorSpace}(30% 40 50 / none)`); } for (const colorSpace of [ "srgb", "srgb-linear", "xyz", "xyz-d50", "xyz-d65" ]) { @@ -256,6 +318,20 @@ test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / .4) 30%, color(${colorSpace} .5 .6 .7 / .8) 90%)`, `color(${resultColorSpace} 0.44285715 0.54285717 0.64285713 / 0.7)`); // Scale down > 100% sum. test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / .4) 12.5%, color(${colorSpace} .5 .6 .7 / .8) 37.5%)`, `color(${resultColorSpace} 0.44285715 0.54285717 0.64285713 / 0.35)`); // Scale up < 100% sum, causes alpha multiplication. test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / .4) 0%, color(${colorSpace} .5 .6 .7 / .8))`, `color(${resultColorSpace} 0.5 0.6 0.7 / 0.8)`); + + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} 2 3 4 / 5), color(${colorSpace} 4 6 8 / 10))`, `color(${resultColorSpace} 3 4.5 6)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} -2 -3 -4), color(${colorSpace} -4 -6 -8))`, `color(${resultColorSpace} -3 -4.5 -6)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} -2 -3 -4 / -5), color(${colorSpace} -4 -6 -8 / -10))`, `color(${resultColorSpace} 0 0 0 / 0)`); + + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none none none), color(${colorSpace} none none none))`, `color(${resultColorSpace} none none none)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none none none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.5 0.6 0.7)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3), color(${colorSpace} none none none))`, `color(${resultColorSpace} 0.1 0.2 0.3)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.3 0.4 0.7)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3), color(${colorSpace} .5 .6 none))`, `color(${resultColorSpace} 0.3 0.4 0.3)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} none .2 .3), color(${colorSpace} .5 none .7))`, `color(${resultColorSpace} 0.5 0.2 0.5)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7))`, `color(${resultColorSpace} 0.3 0.4 0.5)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7 / 0.5))`, `color(${resultColorSpace} 0.3 0.4 0.5 / 0.5)`); + test_valid_value(`color`, `color-mix(in ${colorSpace}, color(${colorSpace} .1 .2 .3 / none), color(${colorSpace} .5 .6 .7 / none))`, `color(${resultColorSpace} 0.3 0.4 0.5 / none)`); } </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid-expected.txt index 36e511b3..f1e4105 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid-expected.txt
@@ -1,5 +1,5 @@ This is a testharness.js-based test. -Found 235 tests; 16 PASS, 219 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 403 tests; 27 PASS, 376 FAIL, 0 TIMEOUT, 0 NOTRUN. PASS e.style['color'] = "currentcolor" should set the property value PASS e.style['color'] = "transparent" should set the property value PASS e.style['color'] = "red" should set the property value @@ -16,6 +16,58 @@ PASS e.style['color'] = "rgb(100, 200, 300)" should set the property value PASS e.style['color'] = "rgb(20, 10, 0, -10)" should set the property value PASS e.style['color'] = "rgb(100%, 200%, 300%)" should set the property value +FAIL e.style['color'] = "rgb(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(128 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(128 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(none none none / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(20% none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(none none none / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(128 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(128 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(20% none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 30% 50%)" should set the property value +PASS e.style['color'] = "hsl(120 30% 50% / 0.5)" should set the property value +FAIL e.style['color'] = "hsl(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(0 0% 0%)" should set the property value +FAIL e.style['color'] = "hsl(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(0 0% 0% / 0)" should set the property value +FAIL e.style['color'] = "hsla(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsla(0 0% 0%)" should set the property value +FAIL e.style['color'] = "hsla(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsla(0 0% 0% / 0)" should set the property value +FAIL e.style['color'] = "hsl(120 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 0% 0%)" should set the property value +FAIL e.style['color'] = "hsl(120 80% none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 80% 0%)" should set the property value +FAIL e.style['color'] = "hsl(120 none 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 0% 50%)" should set the property value +FAIL e.style['color'] = "hsl(120 100% 50% / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 100% 50% / 0)" should set the property value +FAIL e.style['color'] = "hsl(none 100% 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(0 100% 50%)" should set the property value +FAIL e.style['color'] = "hwb(120 30% 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 30% 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(0 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(0 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 80% none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 80% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 none 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 0% 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 30% 50% / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 30% 50% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(none 100% 50% / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(0 100% 50% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(srgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(srgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(srgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -35,6 +87,20 @@ FAIL e.style['color'] = "color(srgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(srgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(srgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(srgb-linear 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(srgb-linear 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(srgb-linear .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -54,6 +120,20 @@ FAIL e.style['color'] = "color(srgb-linear 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(srgb-linear 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(srgb-linear / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(a98-rgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(a98-rgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(a98-rgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -73,6 +153,20 @@ FAIL e.style['color'] = "color(a98-rgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(a98-rgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(a98-rgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(rec2020 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(rec2020 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(rec2020 .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -92,6 +186,20 @@ FAIL e.style['color'] = "color(rec2020 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(rec2020 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(rec2020 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(prophoto-rgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(prophoto-rgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(prophoto-rgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -111,6 +219,20 @@ FAIL e.style['color'] = "color(prophoto-rgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(prophoto-rgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(prophoto-rgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -131,6 +253,12 @@ FAIL e.style['color'] = "color(xyz 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz-d50 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz-d50 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -151,6 +279,12 @@ FAIL e.style['color'] = "color(xyz-d50 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz-d50 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz-d50 / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz-d65 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz-d65 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -171,6 +305,12 @@ FAIL e.style['color'] = "color(xyz-d65 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz-d65 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(xyz-d65 / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(0% 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -185,6 +325,13 @@ FAIL e.style['color'] = "lab(-40% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(50% -20 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(50% 0 -20)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(0% 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -199,6 +346,13 @@ FAIL e.style['color'] = "oklab(-40% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(50% -20 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(50% 0 -20)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(0% 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(0% 0 0deg / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(0% 0 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -217,6 +371,13 @@ FAIL e.style['color'] = "lch(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(10% 20 20 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(10% 20 -700)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(0% 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(0% 0 0deg / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(0% 0 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -235,5 +396,12 @@ FAIL e.style['color'] = "oklch(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(10% 20 20 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(10% 20 -700)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" Harness: the test ran to completion.
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid.html index bfe2726a..22c6abe 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/color-valid.html
@@ -29,26 +29,97 @@ test_valid_value("color", "rgb(20, 10, 0, -10)", "rgba(20, 10, 0, 0)"); test_valid_value("color", "rgb(100%, 200%, 300%)", "rgb(255, 255, 255)"); +test_valid_value("color", "rgb(none none none)", "rgb(0, 0, 0)"); +test_valid_value("color", "rgb(none none none / none)", "rgba(0, 0, 0, 0)"); +test_valid_value("color", "rgb(128 none none)", "rgb(128, 0, 0)"); +test_valid_value("color", "rgb(128 none none / none)", "rgba(128, 0, 0, 0)"); +test_valid_value("color", "rgb(none none none / .5)", "rgba(0, 0, 0, 0.5)"); +test_valid_value("color", "rgb(20% none none)", "rgb(51, 0, 0)"); +test_valid_value("color", "rgb(20% none none / none)", "rgba(51, 0, 0, 0)"); +test_valid_value("color", "rgb(none none none / 50%)", "rgba(0, 0, 0, 0.5)"); +test_valid_value("color", "rgba(none none none)", "rgb(0, 0, 0)"); +test_valid_value("color", "rgba(none none none / none)", "rgba(0, 0, 0, 0)"); +test_valid_value("color", "rgba(128 none none)", "rgb(128, 0, 0)"); +test_valid_value("color", "rgba(128 none none / none)", "rgba(128, 0, 0, 0)"); +test_valid_value("color", "rgba(none none none / .5)", "rgba(0, 0, 0, 0.5)"); +test_valid_value("color", "rgba(20% none none)", "rgb(51, 0, 0)"); +test_valid_value("color", "rgba(20% none none / none)", "rgba(51, 0, 0, 0)"); +test_valid_value("color", "rgba(none none none / 50%)", "rgba(0, 0, 0, 0.5)"); + +test_valid_value("color", "hsl(120 30% 50%)", "rgb(89, 166, 89)"); +test_valid_value("color", "hsl(120 30% 50% / 0.5)", "rgba(89, 166, 89, 0.5)"); +test_valid_value("color", "hsl(none none none)", "rgb(0, 0, 0)"); +test_valid_value("color", "hsl(0 0% 0%)", "rgb(0, 0, 0)"); +test_valid_value("color", "hsl(none none none / none)", "rgba(0, 0, 0, 0)"); +test_valid_value("color", "hsl(0 0% 0% / 0)", "rgba(0, 0, 0, 0)"); +test_valid_value("color", "hsla(none none none)", "rgb(0, 0, 0)"); +test_valid_value("color", "hsla(0 0% 0%)", "rgb(0, 0, 0)"); +test_valid_value("color", "hsla(none none none / none)", "rgba(0, 0, 0, 0)"); +test_valid_value("color", "hsla(0 0% 0% / 0)", "rgba(0, 0, 0, 0)"); +test_valid_value("color", "hsl(120 none none)", "rgb(0, 0, 0)"); +test_valid_value("color", "hsl(120 0% 0%)", "rgb(0, 0, 0)"); +test_valid_value("color", "hsl(120 80% none)", "rgb(0, 0, 0)"); +test_valid_value("color", "hsl(120 80% 0%)", "rgb(0, 0, 0)"); +test_valid_value("color", "hsl(120 none 50%)", "rgb(128, 128, 128)"); +test_valid_value("color", "hsl(120 0% 50%)", "rgb(128, 128, 128)"); +test_valid_value("color", "hsl(120 100% 50% / none)", "rgba(0, 255, 0, 0)"); +test_valid_value("color", "hsl(120 100% 50% / 0)", "rgba(0, 255, 0, 0)"); +test_valid_value("color", "hsl(none 100% 50%)", "rgb(255, 0, 0)"); +test_valid_value("color", "hsl(0 100% 50%)", "rgb(255, 0, 0)"); + +test_valid_value("color", "hwb(120 30% 50%)", "rgb(77, 128, 77)"); +test_valid_value("color", "hwb(120 30% 50% / 0.5)", "rgba(77, 128, 77, 0.5)"); +test_valid_value("color", "hwb(none none none)", "rgb(255, 0, 0)"); +test_valid_value("color", "hwb(0 0% 0%)", "rgb(255, 0, 0)"); +test_valid_value("color", "hwb(none none none / none)", "rgba(255, 0, 0, 0)"); +test_valid_value("color", "hwb(0 0% 0% / 0)", "rgba(255, 0, 0, 0)"); +test_valid_value("color", "hwb(120 none none)", "rgb(0, 255, 0)"); +test_valid_value("color", "hwb(120 0% 0%)", "rgb(0, 255, 0)"); +test_valid_value("color", "hwb(120 80% none)", "rgb(204, 255, 204)"); +test_valid_value("color", "hwb(120 80% 0%)", "rgb(204, 255, 204)"); +test_valid_value("color", "hwb(120 none 50%)", "rgb(0, 128, 0)"); +test_valid_value("color", "hwb(120 0% 50%)", "rgb(0, 128, 0)"); +test_valid_value("color", "hwb(120 30% 50% / none)", "rgba(77, 128, 77, 0)"); +test_valid_value("color", "hwb(120 30% 50% / 0)", "rgba(77, 128, 77, 0)"); +test_valid_value("color", "hwb(none 100% 50% / none)", "rgba(170, 170, 170, 0)"); +test_valid_value("color", "hwb(0 100% 50% / 0)", "rgba(170, 170, 170, 0)"); + + for (const colorSpace of [ "srgb", "srgb-linear", "a98-rgb", "rec2020", "prophoto-rgb" ]) { test_valid_value("color", `color(${colorSpace} 0% 0% 0%)`, `color(${colorSpace} 0 0 0)`); test_valid_value("color", `color(${colorSpace} 10% 10% 10%)`, `color(${colorSpace} 0.1 0.1 0.1)`); test_valid_value("color", `color(${colorSpace} .2 .2 25%)`, `color(${colorSpace} 0.2 0.2 0.25)`); test_valid_value("color", `color(${colorSpace} 0 0 0 / 1)`, `color(${colorSpace} 0 0 0)`); test_valid_value("color", `color(${colorSpace} 0% 0 0 / 0.5)`, `color(${colorSpace} 0 0 0 / 0.5)`); - test_valid_value("color", `color(${colorSpace} 20% 0 10/0.5)`, `color(${colorSpace} 0.2 0 1 / 0.5)`); - test_valid_value("color", `color(${colorSpace} 20% 0 10/50%)`, `color(${colorSpace} 0.2 0 1 / 0.5)`); - test_valid_value("color", `color(${colorSpace} 400% 0 10/50%)`, `color(${colorSpace} 1 0 1 / 0.5)`); - test_valid_value("color", `color(${colorSpace} 50% -160 160)`, `color(${colorSpace} 0.5 0 1)`); - test_valid_value("color", `color(${colorSpace} 50% -200 200)`, `color(${colorSpace} 0.5 0 1)`); + test_valid_value("color", `color(${colorSpace} 20% 0 10/0.5)`, `color(${colorSpace} 0.2 0 10 / 0.5)`); + test_valid_value("color", `color(${colorSpace} 20% 0 10/50%)`, `color(${colorSpace} 0.2 0 10 / 0.5)`); + test_valid_value("color", `color(${colorSpace} 400% 0 10/50%)`, `color(${colorSpace} 4 0 10 / 0.5)`); + test_valid_value("color", `color(${colorSpace} 50% -160 160)`, `color(${colorSpace} 0.5 -160 160)`); + test_valid_value("color", `color(${colorSpace} 50% -200 200)`, `color(${colorSpace} 0.5 -200 200)`); test_valid_value("color", `color(${colorSpace} 0 0 0 / -10%)`, `color(${colorSpace} 0 0 0 / 0)`); test_valid_value("color", `color(${colorSpace} 0 0 0 / 110%)`, `color(${colorSpace} 0 0 0)`); test_valid_value("color", `color(${colorSpace} 0 0 0 / 300%)`, `color(${colorSpace} 0 0 0)`); - test_valid_value("color", `color(${colorSpace} 50% -200)`, `color(${colorSpace} 0.5 0 0)`); + test_valid_value("color", `color(${colorSpace} 50% -200)`, `color(${colorSpace} 0.5 -200 0)`); test_valid_value("color", `color(${colorSpace} 50%)`, `color(${colorSpace} 0.5 0 0)`); test_valid_value("color", `color(${colorSpace})`, `color(${colorSpace} 0 0 0)`); - test_valid_value("color", `color(${colorSpace} 50% -200 / 0.5)`, `color(${colorSpace} 0.5 0 0 / 0.5)`); + test_valid_value("color", `color(${colorSpace} 50% -200 / 0.5)`, `color(${colorSpace} 0.5 -200 0 / 0.5)`); test_valid_value("color", `color(${colorSpace} 50% / 0.5)`, `color(${colorSpace} 0.5 0 0 / 0.5)`); test_valid_value("color", `color(${colorSpace} / 0.5)`, `color(${colorSpace} 0 0 0 / 0.5)`); + test_valid_value("color", `color(${colorSpace} 200 200 200)`, `color(${colorSpace} 200 200 200)`); + test_valid_value("color", `color(${colorSpace} 200 200 200 / 200)`, `color(${colorSpace} 200 200 200)`); + test_valid_value("color", `color(${colorSpace} -200 -200 -200)`, `color(${colorSpace} -200 -200 -200)`); + test_valid_value("color", `color(${colorSpace} -200 -200 -200 / -200)`, `color(${colorSpace} -200 -200 -200 / 0)`); + test_valid_value("color", `color(${colorSpace} 200% 200% 200%)`, `color(${colorSpace} 2 2 2)`); + test_valid_value("color", `color(${colorSpace} 200% 200% 200% / 200%)`, `color(${colorSpace} 2 2 2)`); + test_valid_value("color", `color(${colorSpace} -200% -200% -200% / -200%)`, `color(${colorSpace} -2 -2 -2 / 0)`); + test_valid_value("color", `color(${colorSpace} calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))`, `color(${colorSpace} 1.5 -0.5 0.5 / 0.5)`); + test_valid_value("color", `color(${colorSpace} calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))`, `color(${colorSpace} 1.5 -0.5 0.5 / 0)`); + + test_valid_value("color", `color(${colorSpace} none none none / none)`, `color(${colorSpace} none none none / none)`); + test_valid_value("color", `color(${colorSpace} none none none)`, `color(${colorSpace} none none none)`); + test_valid_value("color", `color(${colorSpace} 10% none none / none)`, `color(${colorSpace} 0.1 none none / none)`); + test_valid_value("color", `color(${colorSpace} none none none / 0.5)`, `color(${colorSpace} none none none / 0.5)`); + test_valid_value("color", `color(${colorSpace} 0 0 0 / none)`, `color(${colorSpace} 0 0 0 / none)`); } for (const colorSpace of [ "xyz", "xyz-d50", "xyz-d65" ]) { @@ -74,6 +145,13 @@ test_valid_value("color", `color(${colorSpace} 1 1 / .5)`, `color(${resultColorSpace} 1 1 0 / 0.5)`); test_valid_value("color", `color(${colorSpace} 1 / 0.5)`, `color(${resultColorSpace} 1 0 0 / 0.5)`); test_valid_value("color", `color(${colorSpace} / 50%)`, `color(${resultColorSpace} 0 0 0 / 0.5)`); + test_valid_value("color", `color(${colorSpace} calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))`, `color(${resultColorSpace} 1.5 -0.5 0.5 / 0.5)`); + + test_valid_value("color", `color(${colorSpace} none none none / none)`, `color(${resultColorSpace} none none none / none)`); + test_valid_value("color", `color(${colorSpace} none none none)`, `color(${resultColorSpace} none none none)`); + test_valid_value("color", `color(${colorSpace} 0.2 none none / none)`, `color(${resultColorSpace} 0.2 none none / none)`); + test_valid_value("color", `color(${colorSpace} none none none / 0.5)`, `color(${resultColorSpace} none none none / 0.5)`); + test_valid_value("color", `color(${colorSpace} 0 0 0 / none)`, `color(${resultColorSpace} 0 0 0 / none)`); } for (const colorSpace of [ "lab", "oklab" ]) { @@ -91,6 +169,14 @@ test_valid_value("color", `${colorSpace}(-40% 0 0)`, `${colorSpace}(0% 0 0)`); test_valid_value("color", `${colorSpace}(50% -20 0)`, `${colorSpace}(50% -20 0)`); test_valid_value("color", `${colorSpace}(50% 0 -20)`, `${colorSpace}(50% 0 -20)`); + test_valid_value("color", `${colorSpace}(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))`, `${colorSpace}(150% -0.5 1.5 / 0.5)`); + test_valid_value("color", `${colorSpace}(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))`, `${colorSpace}(0% 1.5 -1.5 / 0)`); + + test_valid_value("color", `${colorSpace}(none none none / none)`, `${colorSpace}(none none none / none)`); + test_valid_value("color", `${colorSpace}(none none none)`, `${colorSpace}(none none none)`); + test_valid_value("color", `${colorSpace}(20% none none / none)`, `${colorSpace}(20% none none / none)`); + test_valid_value("color", `${colorSpace}(none none none / 0.5)`, `${colorSpace}(none none none / 0.5)`); + test_valid_value("color", `${colorSpace}(0% 0 0 / none)`, `${colorSpace}(0% 0 0 / none)`); } for (const colorSpace of [ "lch", "oklch" ]) { @@ -112,6 +198,14 @@ test_valid_value("color", `${colorSpace}(0% 0 0 / 0.5)`, `${colorSpace}(0% 0 0 / 0.5)`); test_valid_value("color", `${colorSpace}(10% 20 20 / 110%)`, `${colorSpace}(10% 20 20)`); test_valid_value("color", `${colorSpace}(10% 20 -700)`, `${colorSpace}(10% 20 20)`); + test_valid_value("color", `${colorSpace}(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))`, `${colorSpace}(150% 0 40 / 0.5)`); + test_valid_value("color", `${colorSpace}(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))`, `${colorSpace}(0% 1.5 320 / 0)`); + + test_valid_value("color", `${colorSpace}(none none none / none)`, `${colorSpace}(none none none / none)`); + test_valid_value("color", `${colorSpace}(none none none)`, `${colorSpace}(none none none)`); + test_valid_value("color", `${colorSpace}(20% none none / none)`, `${colorSpace}(20% none none / none)`); + test_valid_value("color", `${colorSpace}(none none none / 0.5)`, `${colorSpace}(none none none / 0.5)`); + test_valid_value("color", `${colorSpace}(0% 0 0 / none)`, `${colorSpace}(0% 0 0 / none)`); } </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt index 6b9f5f9..a22d69e 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt
@@ -1,11 +1,19 @@ This is a testharness.js-based test. -Found 586 tests; 0 PASS, 586 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 881 tests; 0 PASS, 881 FAIL, 0 TIMEOUT, 0 NOTRUN. FAIL Property color value 'rgb(from rebeccapurple r g b)' assert_true: 'rgb(from rebeccapurple r g b)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple r g b / alpha)' assert_true: 'rgb(from rebeccapurple r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)' assert_true: 'rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)' assert_true: 'rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rgb(from rebeccapurple r g b) r g b)' assert_true: 'rgb(from rgb(from rebeccapurple r g b) r g b)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from color(display-p3 0 1 0) r g b / alpha)' assert_true: 'rgb(from color(display-p3 0 1 0) r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lab(100% 104.3 -50.9) r g b)' assert_true: 'rgb(from lab(100% 104.3 -50.9) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lab(0% 104.3 -50.9) r g b)' assert_true: 'rgb(from lab(0% 104.3 -50.9) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lch(100% 116 334) r g b)' assert_true: 'rgb(from lch(100% 116 334) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lch(0% 116 334) r g b)' assert_true: 'rgb(from lch(0% 116 334) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklab(100% 0.365 -0.16) r g b)' assert_true: 'rgb(from oklab(100% 0.365 -0.16) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklab(0% 0.365 -0.16) r g b)' assert_true: 'rgb(from oklab(0% 0.365 -0.16) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklch(100% 0.399 336.3) r g b)' assert_true: 'rgb(from oklch(100% 0.399 336.3) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklch(0% 0.399 336.3) r g b)' assert_true: 'rgb(from oklch(0% 0.399 336.3) r g b)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple 0 0 0)' assert_true: 'rgb(from rebeccapurple 0 0 0)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple 0 0 0 / 0)' assert_true: 'rgb(from rebeccapurple 0 0 0 / 0)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple 0 g b / alpha)' assert_true: 'rgb(from rebeccapurple 0 g b / alpha)' is a supported value for color. expected true got false @@ -58,12 +66,31 @@ FAIL Property color value 'rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)' assert_true: 'rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)' assert_true: 'rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple none none none)' assert_true: 'rgb(from rebeccapurple none none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple none none none / none)' assert_true: 'rgb(from rebeccapurple none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple r g none)' assert_true: 'rgb(from rebeccapurple r g none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple r g none / alpha)' assert_true: 'rgb(from rebeccapurple r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple r g b / none)' assert_true: 'rgb(from rebeccapurple r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)' assert_true: 'rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% 40% 60% / 80%) r g b / none)' assert_true: 'rgb(from rgb(20% 40% 60% / 80%) r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(none none none) r g b)' assert_true: 'rgb(from rgb(none none none) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(none none none / none) r g b / alpha)' assert_true: 'rgb(from rgb(none none none / none) r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% none 60%) r g b)' assert_true: 'rgb(from rgb(20% none 60%) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% 40% 60% / none) r g b / alpha)' assert_true: 'rgb(from rgb(20% 40% 60% / none) r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple h s l)' assert_true: 'hsl(from rebeccapurple h s l)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple h s l / alpha)' assert_true: 'hsl(from rebeccapurple h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)' assert_true: 'hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from hsl(from rebeccapurple h s l) h s l)' assert_true: 'hsl(from hsl(from rebeccapurple h s l) h s l)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from color(display-p3 0 1 0) h s l / alpha)' assert_true: 'hsl(from color(display-p3 0 1 0) h s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lab(100% 104.3 -50.9) h s l)' assert_true: 'hsl(from lab(100% 104.3 -50.9) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lab(0% 104.3 -50.9) h s l)' assert_true: 'hsl(from lab(0% 104.3 -50.9) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lch(100% 116 334) h s l)' assert_true: 'hsl(from lch(100% 116 334) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lch(0% 116 334) h s l)' assert_true: 'hsl(from lch(0% 116 334) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklab(100% 0.365 -0.16) h s l)' assert_true: 'hsl(from oklab(100% 0.365 -0.16) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklab(0% 0.365 -0.16) h s l)' assert_true: 'hsl(from oklab(0% 0.365 -0.16) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklch(100% 0.399 336.3) h s l)' assert_true: 'hsl(from oklch(100% 0.399 336.3) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklch(0% 0.399 336.3) h s l)' assert_true: 'hsl(from oklch(0% 0.399 336.3) h s l)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple 0 0% 0%)' assert_true: 'hsl(from rebeccapurple 0 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple 0deg 0% 0%)' assert_true: 'hsl(from rebeccapurple 0deg 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple 0 0% 0% / 0)' assert_true: 'hsl(from rebeccapurple 0 0% 0% / 0)' is a supported value for color. expected true got false @@ -98,12 +125,34 @@ FAIL Property color value 'hsl(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' assert_true: 'hsl(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple calc(h) calc(s) calc(l))' assert_true: 'hsl(from rebeccapurple calc(h) calc(s) calc(l))' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))' assert_true: 'hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple none none none)' assert_true: 'hsl(from rebeccapurple none none none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple none none none / none)' assert_true: 'hsl(from rebeccapurple none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple h s none)' assert_true: 'hsl(from rebeccapurple h s none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple h s none / alpha)' assert_true: 'hsl(from rebeccapurple h s none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple h s l / none)' assert_true: 'hsl(from rebeccapurple h s l / none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple none s l / alpha)' assert_true: 'hsl(from rebeccapurple none s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) h s l / none)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) h s l / none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(none none none) h s l)' assert_true: 'hsl(from hsl(none none none) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(none none none / none) h s l / alpha)' assert_true: 'hsl(from hsl(none none none / none) h s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg none 50% / .5) h s l)' assert_true: 'hsl(from hsl(120deg none 50% / .5) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / none) h s l / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / none) h s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(none 20% 50% / .5) h s l / alpha)' assert_true: 'hsl(from hsl(none 20% 50% / .5) h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple h w b)' assert_true: 'hwb(from rebeccapurple h w b)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple h w b / alpha)' assert_true: 'hwb(from rebeccapurple h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)' assert_true: 'hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)' assert_true: 'hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from hwb(from rebeccapurple h w b) h w b)' assert_true: 'hwb(from hwb(from rebeccapurple h w b) h w b)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from color(display-p3 0 1 0) h w b / alpha)' assert_true: 'hwb(from color(display-p3 0 1 0) h w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lab(100% 104.3 -50.9) h w b)' assert_true: 'hwb(from lab(100% 104.3 -50.9) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lab(0% 104.3 -50.9) h w b)' assert_true: 'hwb(from lab(0% 104.3 -50.9) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lch(100% 116 334) h w b)' assert_true: 'hwb(from lch(100% 116 334) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lch(0% 116 334) h w b)' assert_true: 'hwb(from lch(0% 116 334) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklab(100% 0.365 -0.16) h w b)' assert_true: 'hwb(from oklab(100% 0.365 -0.16) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklab(0% 0.365 -0.16) h w b)' assert_true: 'hwb(from oklab(0% 0.365 -0.16) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklch(100% 0.399 336.3) h w b)' assert_true: 'hwb(from oklch(100% 0.399 336.3) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklch(0% 0.399 336.3) h w b)' assert_true: 'hwb(from oklch(0% 0.399 336.3) h w b)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple 0 0% 0%)' assert_true: 'hwb(from rebeccapurple 0 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple 0deg 0% 0%)' assert_true: 'hwb(from rebeccapurple 0deg 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple 0 0% 0% / 0)' assert_true: 'hwb(from rebeccapurple 0 0% 0% / 0)' is a supported value for color. expected true got false @@ -138,9 +187,25 @@ FAIL Property color value 'hwb(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' assert_true: 'hwb(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple calc(h) calc(w) calc(b))' assert_true: 'hwb(from rebeccapurple calc(h) calc(w) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))' assert_true: 'hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple none none none)' assert_true: 'hwb(from rebeccapurple none none none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple none none none / none)' assert_true: 'hwb(from rebeccapurple none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple h w none)' assert_true: 'hwb(from rebeccapurple h w none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple h w none / alpha)' assert_true: 'hwb(from rebeccapurple h w none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple h w b / none)' assert_true: 'hwb(from rebeccapurple h w b / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple none w b / alpha)' assert_true: 'hwb(from rebeccapurple none w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)' assert_true: 'hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / .5) h w b / none)' assert_true: 'hwb(from hwb(120deg 20% 50% / .5) h w b / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)' assert_true: 'hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(none none none) h w b)' assert_true: 'hwb(from hwb(none none none) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(none none none / none) h w b / alpha)' assert_true: 'hwb(from hwb(none none none / none) h w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg none 50% / .5) h w b)' assert_true: 'hwb(from hwb(120deg none 50% / .5) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / none) h w b / alpha)' assert_true: 'hwb(from hwb(120deg 20% 50% / none) h w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(none 20% 50% / .5) h w b / alpha)' assert_true: 'hwb(from hwb(none 20% 50% / .5) h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l a b)' assert_true: 'lab(from lab(25% 20 50) l a b)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l a b / alpha)' assert_true: 'lab(from lab(25% 20 50) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a b / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(200% 300 400 / 500%) l a b / alpha)' assert_true: 'lab(from lab(200% 300 400 / 500%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(-200% -300 -400 / -500%) l a b / alpha)' assert_true: 'lab(from lab(-200% -300 -400 / -500%) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(from lab(25% 20 50) l a b) l a b)' assert_true: 'lab(from lab(from lab(25% 20 50) l a b) l a b)' is a supported value for color. expected true got false FAIL Property color value 'lab(from color(display-p3 0 0 0) l a b / alpha)' assert_true: 'lab(from color(display-p3 0 0 0) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) 0% 0 0)' assert_true: 'lab(from lab(25% 20 50) 0% 0 0)' is a supported value for color. expected true got false @@ -161,15 +226,30 @@ FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l 35 b / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l 35 b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a 35 / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a 35 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a b / .35)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a b / .35)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'lab(from lab(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'lab(from lab(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l b a)' assert_true: 'lab(from lab(25% 20 50) l b a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l a a / a)' assert_true: 'lab(from lab(25% 20 50) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l b a)' assert_true: 'lab(from lab(25% 20 50 / 40%) l b a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a a / a)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) calc(l) calc(a) calc(b))' assert_true: 'lab(from lab(25% 20 50) calc(l) calc(a) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' assert_true: 'lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) none none none)' assert_true: 'lab(from lab(25% 20 50) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) none none none / none)' assert_true: 'lab(from lab(25% 20 50) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) l a none)' assert_true: 'lab(from lab(25% 20 50) l a none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) l a none / alpha)' assert_true: 'lab(from lab(25% 20 50) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) l a b / none)' assert_true: 'lab(from lab(25% 20 50) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a none / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a b / none)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(none none none) l a b)' assert_true: 'lab(from lab(none none none) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(none none none / none) l a b / alpha)' assert_true: 'lab(from lab(none none none / none) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% none 50) l a b)' assert_true: 'lab(from lab(25% none 50) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50 / none) l a b / alpha)' assert_true: 'lab(from lab(25% 20 50 / none) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l a b)' assert_true: 'oklab(from oklab(25% 20 50) l a b)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l a b / alpha)' assert_true: 'oklab(from oklab(25% 20 50) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a b / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(200% 300 400 / 500%) l a b / alpha)' assert_true: 'oklab(from oklab(200% 300 400 / 500%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(-200% -300 -400 / -500%) l a b / alpha)' assert_true: 'oklab(from oklab(-200% -300 -400 / -500%) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(from oklab(25% 20 50) l a b) l a b)' assert_true: 'oklab(from oklab(from oklab(25% 20 50) l a b) l a b)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from color(display-p3 0 0 0) l a b / alpha)' assert_true: 'oklab(from color(display-p3 0 0 0) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) 0% 0 0)' assert_true: 'oklab(from oklab(25% 20 50) 0% 0 0)' is a supported value for color. expected true got false @@ -190,15 +270,30 @@ FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l 35 b / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l 35 b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a 35 / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a 35 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a b / .35)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a b / .35)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'oklab(from oklab(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'oklab(from oklab(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l b a)' assert_true: 'oklab(from oklab(25% 20 50) l b a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l a a / a)' assert_true: 'oklab(from oklab(25% 20 50) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l b a)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l b a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a a / a)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) calc(l) calc(a) calc(b))' assert_true: 'oklab(from oklab(25% 20 50) calc(l) calc(a) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' assert_true: 'oklab(from oklab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) none none none)' assert_true: 'oklab(from oklab(25% 20 50) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) none none none / none)' assert_true: 'oklab(from oklab(25% 20 50) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) l a none)' assert_true: 'oklab(from oklab(25% 20 50) l a none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) l a none / alpha)' assert_true: 'oklab(from oklab(25% 20 50) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) l a b / none)' assert_true: 'oklab(from oklab(25% 20 50) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a none / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a b / none)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(none none none) l a b)' assert_true: 'oklab(from oklab(none none none) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(none none none / none) l a b / alpha)' assert_true: 'oklab(from oklab(none none none / none) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% none 50) l a b)' assert_true: 'oklab(from oklab(25% none 50) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50 / none) l a b / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / none) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) l c h)' assert_true: 'lch(from lch(70% 45 30) l c h)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) l c h / alpha)' assert_true: 'lch(from lch(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false -FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h/ alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h/ alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(200% 300 400 / 500%) l c h / alpha)' assert_true: 'lch(from lch(200% 300 400 / 500%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(-200% -300 -400 / -500%) l c h / alpha)' assert_true: 'lch(from lch(-200% -300 -400 / -500%) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(from lch(70% 45 30) l c h) l c h)' assert_true: 'lch(from lch(from lch(70% 45 30) l c h) l c h)' is a supported value for color. expected true got false FAIL Property color value 'lch(from color(display-p3 0 0 0) l c h / alpha)' assert_true: 'lch(from color(display-p3 0 0 0) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lab(70% 45 30) l c h / alpha)' assert_true: 'lch(from lab(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false @@ -226,6 +321,10 @@ FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c 25 / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c 25 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h / .25)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h / .25)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'lch(from lch(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'lch(from lch(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) 50% 120 400deg / 500)' assert_true: 'lch(from lch(70% 45 30 / 40%) 50% 120 400deg / 500)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) 50% 120 -400deg / -500)' assert_true: 'lch(from lch(70% 45 30 / 40%) 50% 120 -400deg / -500)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) alpha c h / l)' assert_true: 'lch(from lch(70% 45 30) alpha c h / l)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) l c c / alpha)' assert_true: 'lch(from lch(70% 45 30) l c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) alpha c h / alpha)' assert_true: 'lch(from lch(70% 45 30) alpha c h / alpha)' is a supported value for color. expected true got false @@ -236,9 +335,22 @@ FAIL Property color value 'lch(from lch(70% 45 30 / 40%) alpha c c / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) alpha c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) calc(l) calc(c) calc(h))' assert_true: 'lch(from lch(70% 45 30) calc(l) calc(c) calc(h))' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' assert_true: 'lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) none none none)' assert_true: 'lch(from lch(70% 45 30) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) none none none / none)' assert_true: 'lch(from lch(70% 45 30) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) l c none)' assert_true: 'lch(from lch(70% 45 30) l c none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) l c none / alpha)' assert_true: 'lch(from lch(70% 45 30) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) l c h / none)' assert_true: 'lch(from lch(70% 45 30) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c none / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h / none)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(none none none) l c h)' assert_true: 'lch(from lch(none none none) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(none none none / none) l c h / alpha)' assert_true: 'lch(from lch(none none none / none) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% none 30) l c h)' assert_true: 'lch(from lch(70% none 30) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / none) l c h / alpha)' assert_true: 'lch(from lch(70% 45 30 / none) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) l c h)' assert_true: 'oklch(from oklch(70% 45 30) l c h)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) l c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false -FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h/ alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h/ alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(200% 300 400 / 500%) l c h / alpha)' assert_true: 'oklch(from oklch(200% 300 400 / 500%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(-200% -300 -400 / -500%) l c h / alpha)' assert_true: 'oklch(from oklch(-200% -300 -400 / -500%) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(from oklch(70% 45 30) l c h) l c h)' assert_true: 'oklch(from oklch(from oklch(70% 45 30) l c h) l c h)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from color(display-p3 0 0 0) l c h / alpha)' assert_true: 'oklch(from color(display-p3 0 0 0) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklab(70% 45 30) l c h / alpha)' assert_true: 'oklch(from oklab(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false @@ -266,6 +378,10 @@ FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c 25 / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c 25 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c 25deg / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c 25deg / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h / .25)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h / .25)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) 50% 120 400deg / 500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) 50% 120 400deg / 500)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) 50% 120 -400deg / -500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) 50% 120 -400deg / -500)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) alpha c h / l)' assert_true: 'oklch(from oklch(70% 45 30) alpha c h / l)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) l c c / alpha)' assert_true: 'oklch(from oklch(70% 45 30) l c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) alpha c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30) alpha c h / alpha)' is a supported value for color. expected true got false @@ -276,6 +392,17 @@ FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) alpha c c / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) alpha c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) calc(l) calc(c) calc(h))' assert_true: 'oklch(from oklch(70% 45 30) calc(l) calc(c) calc(h))' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' assert_true: 'oklch(from oklch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) none none none)' assert_true: 'oklch(from oklch(70% 45 30) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) none none none / none)' assert_true: 'oklch(from oklch(70% 45 30) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) l c none)' assert_true: 'oklch(from oklch(70% 45 30) l c none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) l c none / alpha)' assert_true: 'oklch(from oklch(70% 45 30) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) l c h / none)' assert_true: 'oklch(from oklch(70% 45 30) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c none / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h / none)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(none none none) l c h)' assert_true: 'oklch(from oklch(none none none) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(none none none / none) l c h / alpha)' assert_true: 'oklch(from oklch(none none none / none) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% none 30) l c h)' assert_true: 'oklch(from oklch(70% none 30) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / none) l c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / none) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g b)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b)' is a supported value for color. expected true got false @@ -307,6 +434,14 @@ FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 20% / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0.2)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 20%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4 / 5)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4 / -5)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400% / 500%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400% / -500%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb g b r)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb b alpha r / g)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r r r / r)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r r r / r)' is a supported value for color. expected true got false @@ -315,8 +450,27 @@ FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb b alpha r / g)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r r r / r)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb alpha alpha alpha / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3) srgb r g b)' assert_true: 'color(from color(srgb 1.7 1.5 1.3) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3) srgb r g b / alpha)' assert_true: 'color(from color(srgb 1.7 1.5 1.3) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b)' assert_true: 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b / alpha)' assert_true: 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b / alpha)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b / alpha)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb calc(r) calc(g) calc(b))' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb none none none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb none none none / none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g none / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g none / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb none none none) srgb r g b)' assert_true: 'color(from color(srgb none none none) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb none none none / none) srgb r g b / alpha)' assert_true: 'color(from color(srgb none none none / none) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 none 0.3) srgb r g b)' assert_true: 'color(from color(srgb 0.7 none 0.3) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / none) srgb r g b / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / none) srgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b)' is a supported value for color. expected true got false @@ -348,6 +502,14 @@ FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 20% / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0.2)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 20%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4 / 5)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4 / -5)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400% / 500%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400% / -500%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear g b r)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear b alpha r / g)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r r r / r)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r r r / r)' is a supported value for color. expected true got false @@ -356,8 +518,27 @@ FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear b alpha r / g)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r r r / r)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear alpha alpha alpha / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear calc(r) calc(g) calc(b))' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none / none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g none / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear none none none) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear none none none) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear none none none / none) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear none none none / none) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 none 0.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 0.7 none 0.3) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / none) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / none) srgb-linear r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b)' is a supported value for color. expected true got false @@ -389,6 +570,14 @@ FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 20% / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0.2)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 20%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4 / 5)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4 / -5)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400% / 500%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400% / -500%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb g b r)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb b alpha r / g)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r r r / r)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r r r / r)' is a supported value for color. expected true got false @@ -397,8 +586,27 @@ FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb b alpha r / g)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r r r / r)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb alpha alpha alpha / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb calc(r) calc(g) calc(b))' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none / none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g none / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb none none none) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb none none none) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb none none none / none) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb none none none / none) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 none 0.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 0.7 none 0.3) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / none) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / none) a98-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b)' is a supported value for color. expected true got false @@ -430,6 +638,14 @@ FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 20% / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0.2)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 20%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4 / 5)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4 / -5)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400% / 500%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400% / -500%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 g b r)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 b alpha r / g)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r r r / r)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r r r / r)' is a supported value for color. expected true got false @@ -438,8 +654,27 @@ FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 b alpha r / g)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r r r / r)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 alpha alpha alpha / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 calc(r) calc(g) calc(b))' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none / none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g none / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 none none none) rec2020 r g b)' assert_true: 'color(from color(rec2020 none none none) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 none none none / none) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 none none none / none) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 none 0.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 0.7 none 0.3) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / none) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / none) rec2020 r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b)' is a supported value for color. expected true got false @@ -471,6 +706,14 @@ FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 20% / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0.2)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 20%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4 / 5)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4 / -5)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400% / 500%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400% / -500%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb g b r)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb b alpha r / g)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r r r / r)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r r r / r)' is a supported value for color. expected true got false @@ -479,8 +722,27 @@ FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb b alpha r / g)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r r r / r)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb alpha alpha alpha / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb calc(r) calc(g) calc(b))' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none / none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g none / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb none none none) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb none none none) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb none none none / none) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb none none none / none) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 none 0.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 0.7 none 0.3) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / none) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / none) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y z)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y z)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y z / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z)' is a supported value for color. expected true got false @@ -511,6 +773,17 @@ FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x x x / x)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x x x / x)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz calc(x) calc(y) calc(z))' assert_true: 'color(from color(xyz 7 -20.5 100) xyz calc(x) calc(y) calc(z))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz calc(x) calc(y) calc(z) / calc(alpha))' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz calc(x) calc(y) calc(z) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz none none none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz none none none / none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y none / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y z / none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y none / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / none)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz none none none) xyz x y z)' assert_true: 'color(from color(xyz none none none) xyz x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz none none none / none) xyz x y z / alpha)' assert_true: 'color(from color(xyz none none none / none) xyz x y z / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 none 100) xyz x y z)' assert_true: 'color(from color(xyz 7 none 100) xyz x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100 / none) xyz x y z / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100 / none) xyz x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z)' is a supported value for color. expected true got false @@ -541,6 +814,17 @@ FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x x x / x)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x x x / x)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 calc(x) calc(y) calc(z))' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 calc(x) calc(y) calc(z))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 calc(x) calc(y) calc(z) / calc(alpha))' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 calc(x) calc(y) calc(z) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none / none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y none / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 none none none) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 none none none) xyz-d50 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 none none none / none) xyz-d50 x y z / alpha)' assert_true: 'color(from color(xyz-d50 none none none / none) xyz-d50 x y z / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 none 100) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 7 none 100) xyz-d50 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / none) xyz-d50 x y z / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / none) xyz-d50 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z)' is a supported value for color. expected true got false @@ -571,6 +855,17 @@ FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x x x / x)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x x x / x)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 calc(x) calc(y) calc(z))' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 calc(x) calc(y) calc(z))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 calc(x) calc(y) calc(z) / calc(alpha))' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 calc(x) calc(y) calc(z) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none / none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y none / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 none none none) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 none none none) xyz-d65 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)' assert_true: 'color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 none 100) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 7 none 100) xyz-d65 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from var(--bg-color) r g b / 80%)' assert_equals: expected "rgba(0, 0, 255, 0.8)" but got "rgb(0, 0, 0)" FAIL Property color value 'lch(from var(--color) calc(l / 2) c h)' assert_equals: expected "lch(23.138971% 67.989716 134.39125)" but got "rgb(0, 0, 0)" FAIL Property color value 'rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))' assert_equals: expected "rgb(76, 76, 76)" but got "rgb(0, 0, 0)"
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-computed.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-computed.html index b7eccdb..3c72f56 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-computed.html +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-computed.html
@@ -33,8 +33,16 @@ // Test nesting relative colors. test_computed_value(`color`, `rgb(from rgb(from rebeccapurple r g b) r g b)`, `rgb(102, 51, 153)`); - // Testing non-sRGB origin colors to see gamut clipping. - test_computed_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 255, 0)`); + // Testing non-sRGB origin colors to see gamut mapping. + test_computed_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0). + test_computed_value(`color`, `rgb(from lab(100% 104.3 -50.9) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_computed_value(`color`, `rgb(from lab(0% 104.3 -50.9) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_computed_value(`color`, `rgb(from lch(100% 116 334) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_computed_value(`color`, `rgb(from lch(0% 116 334) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_computed_value(`color`, `rgb(from oklab(100% 0.365 -0.16) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255). + test_computed_value(`color`, `rgb(from oklab(0% 0.365 -0.16) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24). + test_computed_value(`color`, `rgb(from oklch(100% 0.399 336.3) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255). + test_computed_value(`color`, `rgb(from oklch(0% 0.399 336.3) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24). // Testing replacement with 0. test_computed_value(`color`, `rgb(from rebeccapurple 0 0 0)`, `rgb(0, 0, 0)`); @@ -105,6 +113,20 @@ test_computed_value(`color`, `rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)`, `rgb(102, 51, 10)`); test_computed_value(`color`, `rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))`, `rgba(51, 102, 153, 0.8)`); + // Testing with 'none'. + // NOTE: Serialization of rgb() with 'none' components is still under discussion - https://github.com/w3c/csswg-drafts/issues/6959 + test_computed_value(`color`, `rgb(from rebeccapurple none none none)`, `rgb(0, 0, 0)`); + test_computed_value(`color`, `rgb(from rebeccapurple none none none / none)`, `rgba(0, 0, 0, 0)`); + test_computed_value(`color`, `rgb(from rebeccapurple r g none)`, `rgb(102, 51, 0)`); + test_computed_value(`color`, `rgb(from rebeccapurple r g none / alpha)`, `rgb(102, 51, 0)`); + test_computed_value(`color`, `rgb(from rebeccapurple r g b / none)`, `rgba(102, 51, 153, 0)`); + test_computed_value(`color`, `rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)`, `rgba(51, 102, 0, 0.8)`); + test_computed_value(`color`, `rgb(from rgb(20% 40% 60% / 80%) r g b / none)`, `rgba(51, 102, 153, 0)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_computed_value(`color`, `rgb(from rgb(none none none) r g b)`, `rgb(0, 0, 0)`); + test_computed_value(`color`, `rgb(from rgb(none none none / none) r g b / alpha)`, `rgba(0, 0, 0, 0)`); + test_computed_value(`color`, `rgb(from rgb(20% none 60%) r g b)`, `rgb(51, 0, 153)`); + test_computed_value(`color`, `rgb(from rgb(20% 40% 60% / none) r g b / alpha)`, `rgba(51, 102, 153, 0)`); // hsl(from ...) @@ -117,8 +139,16 @@ // Test nesting relative colors. test_computed_value(`color`, `hsl(from hsl(from rebeccapurple h s l) h s l)`, `rgb(102, 51, 153)`); - // Testing non-sRGB origin colors to see gamut clipping. - test_computed_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 255, 0)`); + // Testing non-sRGB origin colors to see gamut mapping. + test_computed_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0). + test_computed_value(`color`, `hsl(from lab(100% 104.3 -50.9) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_computed_value(`color`, `hsl(from lab(0% 104.3 -50.9) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_computed_value(`color`, `hsl(from lch(100% 116 334) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_computed_value(`color`, `hsl(from lch(0% 116 334) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_computed_value(`color`, `hsl(from oklab(100% 0.365 -0.16) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255). + test_computed_value(`color`, `hsl(from oklab(0% 0.365 -0.16) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24). + test_computed_value(`color`, `hsl(from oklch(100% 0.399 336.3) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255). + test_computed_value(`color`, `hsl(from oklch(0% 0.399 336.3) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24). // Testing replacement with 0. test_computed_value(`color`, `hsl(from rebeccapurple 0 0% 0%)`, `rgb(0, 0, 0)`); @@ -162,6 +192,22 @@ test_computed_value(`color`, `hsl(from rebeccapurple calc(h) calc(s) calc(l))`, `rgb(102, 51, 153)`); test_computed_value(`color`, `hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))`, `rgba(51, 102, 153, 0.8)`); + // Testing with 'none'. + test_computed_value(`color`, `hsl(from rebeccapurple none none none)`, `rgb(0, 0, 0)`); + test_computed_value(`color`, `hsl(from rebeccapurple none none none / none)`, `rgba(0, 0, 0, 0)`); + test_computed_value(`color`, `hsl(from rebeccapurple h s none)`, `rgb(0, 0, 0)`); + test_computed_value(`color`, `hsl(from rebeccapurple h s none / alpha)`, `rgb(0, 0, 0)`); + test_computed_value(`color`, `hsl(from rebeccapurple h s l / none)`, `rgba(102, 51, 153, 0)`); + test_computed_value(`color`, `hsl(from rebeccapurple none s l / alpha)`, `rgb(153, 51, 51)`); + test_computed_value(`color`, `hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)`, `rgba(0, 0, 0, 0.5)`); + test_computed_value(`color`, `hsl(from hsl(120deg 20% 50% / .5) h s l / none)`, `rgba(102, 153, 102, 0)`); + test_computed_value(`color`, `hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)`, `rgba(153, 102, 102, 0.5)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_computed_value(`color`, `hsl(from hsl(none none none) h s l)`, `rgb(0, 0, 0)`); + test_computed_value(`color`, `hsl(from hsl(none none none / none) h s l / alpha)`, `rgba(0, 0, 0, 0)`); + test_computed_value(`color`, `hsl(from hsl(120deg none 50% / .5) h s l)`, `rgb(128, 128, 128)`); + test_computed_value(`color`, `hsl(from hsl(120deg 20% 50% / none) h s l / alpha)`, `rgba(102, 153, 102, 0)`); + test_computed_value(`color`, `hsl(from hsl(none 20% 50% / .5) h s l / alpha)`, `rgba(153, 102, 102, 0.5)`); // hwb(from ...) @@ -174,8 +220,16 @@ // Test nesting relative colors. test_computed_value(`color`, `hwb(from hwb(from rebeccapurple h w b) h w b)`, `rgb(102, 51, 153)`); - // Testing non-sRGB origin colors to see gamut clipping. - test_computed_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 255, 0)`); + // Testing non-sRGB origin colors to see gamut mapping. + test_computed_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0). + test_computed_value(`color`, `hwb(from lab(100% 104.3 -50.9) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_computed_value(`color`, `hwb(from lab(0% 104.3 -50.9) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_computed_value(`color`, `hwb(from lch(100% 116 334) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_computed_value(`color`, `hwb(from lch(0% 116 334) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_computed_value(`color`, `hwb(from oklab(100% 0.365 -0.16) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255). + test_computed_value(`color`, `hwb(from oklab(0% 0.365 -0.16) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24). + test_computed_value(`color`, `hwb(from oklch(100% 0.399 336.3) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255). + test_computed_value(`color`, `hwb(from oklch(0% 0.399 336.3) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24). // Testing replacement with 0. test_computed_value(`color`, `hwb(from rebeccapurple 0 0% 0%)`, `rgb(255, 0, 0)`); @@ -219,11 +273,30 @@ test_computed_value(`color`, `hwb(from rebeccapurple calc(h) calc(w) calc(b))`, `rgb(102, 51, 153)`); test_computed_value(`color`, `hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))`, `rgba(51, 102, 153, 0.8)`); + // Testing with 'none'. + test_computed_value(`color`, `hwb(from rebeccapurple none none none)`, `rgb(255, 0, 0)`); + test_computed_value(`color`, `hwb(from rebeccapurple none none none / none)`, `rgba(255, 0, 0, 0)`); + test_computed_value(`color`, `hwb(from rebeccapurple h w none)`, `rgb(153, 51, 255)`); + test_computed_value(`color`, `hwb(from rebeccapurple h w none / alpha)`, `rgb(153, 51, 255)`); + test_computed_value(`color`, `hwb(from rebeccapurple h w b / none)`, `rgba(102, 51, 153, 0)`); + test_computed_value(`color`, `hwb(from rebeccapurple none w b / alpha)`, `rgb(153, 51, 51)`); + test_computed_value(`color`, `hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)`, `rgba(51, 255, 51, 0.5)`); + test_computed_value(`color`, `hwb(from hwb(120deg 20% 50% / .5) h w b / none)`, `rgba(51, 128, 51, 0)`); + test_computed_value(`color`, `hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)`, `rgba(128, 51, 51, 0.5)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_computed_value(`color`, `hwb(from hwb(none none none) h w b)`, `rgb(255, 0, 0)`); + test_computed_value(`color`, `hwb(from hwb(none none none / none) h w b / alpha)`, `rgba(255, 0, 0, 0)`); + test_computed_value(`color`, `hwb(from hwb(120deg none 50% / .5) h w b)`, `rgb(0, 128, 0)`); + test_computed_value(`color`, `hwb(from hwb(120deg 20% 50% / none) h w b / alpha)`, `rgba(51, 128, 51, 0)`); + test_computed_value(`color`, `hwb(from hwb(none 20% 50% / .5) h w b / alpha)`, `rgba(128, 51, 51, 0.5)`); + for (const colorSpace of [ "lab", "oklab" ]) { // Testing no modifications. test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l a b)`, `${colorSpace}(25% 20 50)`); test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l a b / alpha)`, `${colorSpace}(25% 20 50)`); test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l a b / alpha)`, `${colorSpace}(25% 20 50 / 0.4)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(200% 300 400 / 500%) l a b / alpha)`, `${colorSpace}(200% 300 400)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(-200% -300 -400 / -500%) l a b / alpha)`, `${colorSpace}(0% -300 -400 / 0)`); // Test nesting relative colors. test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(from ${colorSpace}(25% 20 50) l a b) l a b)`, `${colorSpace}(25% 20 50)`); @@ -252,6 +325,8 @@ test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l 35 b / alpha)`, `${colorSpace}(25% 35 50 / 0.4)`); test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l a 35 / alpha)`, `${colorSpace}(25% 20 35 / 0.4)`); test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l a b / .35)`, `${colorSpace}(25% 20 50 / 0.35)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) 200% 300 400 / 500)`, `${colorSpace}(200% 300 400)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) -200% -300 -400 / -500)`, `${colorSpace}(0% -300 -400 / 0)`); // Testing valid permutation (types match). test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l b a)`, `${colorSpace}(25% 50 20)`); @@ -262,6 +337,20 @@ // Testing with calc(). test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) calc(l) calc(a) calc(b))`, `${colorSpace}(25% 20 50)`); test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))`, `${colorSpace}(25% 20 50 / 0.4)`); + + // Testing with 'none'. + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) none none none)`, `${colorSpace}(none none none)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) none none none / none)`, `${colorSpace}(none none none / none)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l a none)`, `${colorSpace}(25% 20 none)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l a none / alpha)`, `${colorSpace}(25% 20 none)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l a b / none)`, `${colorSpace}(25% 20 50 / none)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l a none / alpha)`, `${colorSpace}(25% 20 none / 0.4)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l a b / none)`, `${colorSpace}(25% 20 50 / none)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(none none none) l a b)`, `${colorSpace}(0% 0 0)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(none none none / none) l a b / alpha)`, `${colorSpace}(0% 0 0 / 0)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% none 50) l a b)`, `${colorSpace}(25% 0 50)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / none) l a b / alpha)`, `${colorSpace}(25% 20 50 / 0)`); } for (const colorSpace of [ "lch", "oklch" ]) { @@ -270,12 +359,14 @@ // Testing no modifications. test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) l c h)`, `${colorSpace}(70% 45 30)`); test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) l c h / alpha)`, `${colorSpace}(70% 45 30)`); - test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c h/ alpha)`, `${colorSpace}(70% 45 30 / 0.4)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c h / alpha)`, `${colorSpace}(70% 45 30 / 0.4)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(200% 300 400 / 500%) l c h / alpha)`, `${colorSpace}(200% 300 40)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(-200% -300 -400 / -500%) l c h / alpha)`, `${colorSpace}(0% 0 320 / 0)`); // Test nesting relative colors. test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(from ${colorSpace}(70% 45 30) l c h) l c h)`, `${colorSpace}(70% 45 30)`); - // Testing non-sRGB origin colors to see gamut clipping. + // Testing non-sRGB origin colors (no gamut mapping will happen since the destination is not a bounded RGB color space). test_computed_value(`color`, `${colorSpace}(from color(display-p3 0 0 0) l c h / alpha)`, `${colorSpace}(0% 0 0)`); test_computed_value(`color`, `${colorSpace}(from ${rectangularForm}(70% 45 30) l c h / alpha)`, `${colorSpace}(70% 54.08327 33.690067)`); @@ -306,6 +397,10 @@ test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c 25 / alpha)`, `${colorSpace}(70% 45 25 / 0.4)`); test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c 25deg / alpha)`, `${colorSpace}(70% 45 25 / 0.4)`); test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c h / .25)`, `${colorSpace}(70% 45 30 / 0.25)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) 200% 300 400 / 500)`, `${colorSpace}(200% 300 40)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) -200% -300 -400 / -500)`, `${colorSpace}(0% 0 320 / 0)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) 50% 120 400deg / 500)`, `${colorSpace}(50% 120 40)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) 50% 120 -400deg / -500)`, `${colorSpace}(50% 120 320 / 0)`); // Testing valid permutation (types match). // NOTE: 'c' is a vaild hue, as hue is <angle>|<number>. @@ -321,6 +416,20 @@ // Testing with calc(). test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) calc(l) calc(c) calc(h))`, `${colorSpace}(70% 45 30)`); test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))`, `${colorSpace}(70% 45 30 / 0.4)`); + + // Testing with 'none'. + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) none none none)`, `${colorSpace}(none none none)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) none none none / none)`, `${colorSpace}(none none none / none)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) l c none)`, `${colorSpace}(70% 45 none)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) l c none / alpha)`, `${colorSpace}(70% 45 none)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) l c h / none)`, `${colorSpace}(70% 45 30 / none)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c none / alpha)`, `${colorSpace}(70% 45 none / 0.4)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c h / none)`, `${colorSpace}(70% 45 30 / none)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(none none none) l c h)`, `${colorSpace}(0% 0 0)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(none none none / none) l c h / alpha)`, `${colorSpace}(0% 0 0 / 0)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% none 30) l c h)`, `${colorSpace}(70% 0 30)`); + test_computed_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / none) l c h / alpha)`, `${colorSpace}(70% 45 30 / 0)`); } for (const colorSpace of [ "srgb", "srgb-linear", "a98-rgb", "rec2020", "prophoto-rgb" ]) { @@ -362,6 +471,14 @@ test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r g 20% / alpha)`, `color(${colorSpace} 0.7 0.5 0.2 / 0.4)`); test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r g b / 0.2)`, `color(${colorSpace} 0.7 0.5 0.3 / 0.2)`); test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r g b / 20%)`, `color(${colorSpace} 0.7 0.5 0.3 / 0.2)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} 2 3 4)`, `color(${colorSpace} 2 3 4)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} 2 3 4 / 5)`, `color(${colorSpace} 2 3 4)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} -2 -3 -4)`, `color(${colorSpace} -2 -3 -4)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} -2 -3 -4 / -5)`, `color(${colorSpace} -2 -3 -4 / 0)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} 200% 300% 400%)`, `color(${colorSpace} 2 3 4)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} 200% 300% 400% / 500%)`, `color(${colorSpace} 2 3 4)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} -200% -300% -400%)`, `color(${colorSpace} -2 -3 -4)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} -200% -300% -400% / -500%)`, `color(${colorSpace} -2 -3 -4 / 0)`); // Testing valid permutation (types match). test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} g b r)`, `color(${colorSpace} 0.5 0.3 0.7)`); @@ -373,9 +490,33 @@ test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r r r / r)`, `color(${colorSpace} 0.7 0.7 0.7 / 0.7)`); test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} alpha alpha alpha / alpha)`, `color(${colorSpace} 0.4 0.4 0.4 / 0.4)`); + // Testing out of gamut components. + test_computed_value(`color`, `color(from color(${colorSpace} 1.7 1.5 1.3) ${colorSpace} r g b)`, `color(${colorSpace} 1.7 1.5 1.3)`); + test_computed_value(`color`, `color(from color(${colorSpace} 1.7 1.5 1.3) ${colorSpace} r g b / alpha)`, `color(${colorSpace} 1.7 1.5 1.3)`); + test_computed_value(`color`, `color(from color(${colorSpace} 1.7 1.5 1.3 / 140%) ${colorSpace} r g b)`, `color(${colorSpace} 1.7 1.5 1.3)`); + test_computed_value(`color`, `color(from color(${colorSpace} 1.7 1.5 1.3 / 140%) ${colorSpace} r g b / alpha)`, `color(${colorSpace} 1.7 1.5 1.3)`); + test_computed_value(`color`, `color(from color(${colorSpace} -0.7 -0.5 -0.3) ${colorSpace} r g b)`, `color(${colorSpace} -0.7 -0.5 -0.3)`); + test_computed_value(`color`, `color(from color(${colorSpace} -0.7 -0.5 -0.3) ${colorSpace} r g b / alpha)`, `color(${colorSpace} -0.7 -0.5 -0.3)`); + test_computed_value(`color`, `color(from color(${colorSpace} -0.7 -0.5 -0.3 / -40%) ${colorSpace} r g b)`, `color(${colorSpace} -0.7 -0.5 -0.3)`); + test_computed_value(`color`, `color(from color(${colorSpace} -0.7 -0.5 -0.3 / -40%) ${colorSpace} r g b / alpha)`, `color(${colorSpace} -0.7 -0.5 -0.3 / 0)`); + // Testing with calc(). test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} calc(r) calc(g) calc(b))`, `color(${colorSpace} 0.7 0.5 0.3)`); test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} calc(r) calc(g) calc(b) / calc(alpha))`, `color(${colorSpace} 0.7 0.5 0.3 / 0.4)`); + + // Testing with 'none'. + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} none none none)`, `color(${colorSpace} none none none)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} none none none / none)`, `color(${colorSpace} none none none / none)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r g none)`, `color(${colorSpace} 0.7 0.5 none)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r g none / alpha)`, `color(${colorSpace} 0.7 0.5 none)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r g b / none)`, `color(${colorSpace} 0.7 0.5 0.3 / none)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r g none / alpha)`, `color(${colorSpace} 0.7 0.5 none / 0.4)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r g b / none)`, `color(${colorSpace} 0.7 0.5 0.3 / none)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_computed_value(`color`, `color(from color(${colorSpace} none none none) ${colorSpace} r g b)`, `color(${colorSpace} 0 0 0)`); + test_computed_value(`color`, `color(from color(${colorSpace} none none none / none) ${colorSpace} r g b / alpha)`, `color(${colorSpace} 0 0 0 / 0)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 none 0.3) ${colorSpace} r g b)`, `color(${colorSpace} 0.7 0 0.3)`); + test_computed_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / none) ${colorSpace} r g b / alpha)`, `color(${colorSpace} 0.7 0.5 0.3 / 0)`); } for (const colorSpace of [ "xyz", "xyz-d50", "xyz-d65" ]) { @@ -422,6 +563,20 @@ // Testing with calc(). test_computed_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} calc(x) calc(y) calc(z))`, `color(${resultColorSpace} 7 -20.5 100)`); test_computed_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / 40%) ${colorSpace} calc(x) calc(y) calc(z) / calc(alpha))`, `color(${resultColorSpace} 7 -20.5 100 / 0.4)`); + + // Testing with 'none'. + test_computed_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} none none none)`, `color(${resultColorSpace} none none none)`); + test_computed_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} none none none / none)`, `color(${resultColorSpace} none none none / none)`); + test_computed_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x y none)`, `color(${resultColorSpace} 7 -20.5 none)`); + test_computed_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x y none / alpha)`, `color(${resultColorSpace} 7 -20.5 none)`); + test_computed_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x y z / none)`, `color(${resultColorSpace} 7 -20.5 100 / none)`); + test_computed_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / 40%) ${colorSpace} x y none / alpha)`, `color(${resultColorSpace} 7 -20.5 none / 0.4)`); + test_computed_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / 40%) ${colorSpace} x y z / none)`, `color(${resultColorSpace} 7 -20.5 100 / none)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_computed_value(`color`, `color(from color(${colorSpace} none none none) ${colorSpace} x y z)`, `color(${resultColorSpace} 0 0 0)`); + test_computed_value(`color`, `color(from color(${colorSpace} none none none / none) ${colorSpace} x y z / alpha)`, `color(${resultColorSpace} 0 0 0 / 0)`); + test_computed_value(`color`, `color(from color(${colorSpace} 7 none 100) ${colorSpace} x y z)`, `color(${resultColorSpace} 7 0 100)`); + test_computed_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / none) ${colorSpace} x y z / alpha)`, `color(${resultColorSpace} 7 -20.5 100 / 0)`); } // Spec Examples
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-invalid.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-invalid.html index c6f19e1e8..6fbb5aa3 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-invalid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-invalid.html
@@ -27,6 +27,10 @@ test_invalid_value(`color`, `rgb(from rebeccapurple l g b)`); test_invalid_value(`color`, `rgb(from rebeccapurple h g b)`); + // Testing invalid function name variation (only rgb() is valid, rgba() is invalid) + test_invalid_value(`color`, `rgba(from rebeccapurple r g b)`); + test_invalid_value(`color`, `rgba(from rgb(10%, 20%, 30%, 40%) r g b / alpha)`); + // hsl(from ...) @@ -53,6 +57,9 @@ test_invalid_value(`color`, `hsl(from rebeccapurple x s l)`); test_invalid_value(`color`, `hsl(from rebeccapurple h g b)`); + // Testing invalid function name variation (only hsl() is valid, hsla() is invalid) + test_invalid_value(`color`, `hsla(from rebeccapurple h s l)`); + test_invalid_value(`color`, `hsla(from rgb(10%, 20%, 30%, 40%) h s l / alpha)`); // hwb(from ...) @@ -125,34 +132,34 @@ for (const colorSpace of [ "srgb", "srgb-linear", "a98-rgb", "rec2020", "prophoto-rgb" ]) { // Testing invalid values. - test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} 10deg g b)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r 10deg b)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r g 10deg)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r g b / 10deg)`, `rgba(0, 0, 0, 0)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} 10deg g b)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r 10deg b)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r g 10deg)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r g b / 10deg)`); // Testing invalid component names - test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} red g b)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} x g b)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} l g b)`, `rgba(0, 0, 0, 0)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} red g b)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} x g b)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} l g b)`); } for (const colorSpace of [ "xyz", "xyz-d50", "xyz-d65" ]) { // Testing invalid permutation (types don't match). - test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} z alpha x / y)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / 40%) ${colorSpace} z alpha x / y)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / 40%) ${colorSpace} alpha alpha alpha / alpha)`, `rgba(0, 0, 0, 0)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} z alpha x / y)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} alpha alpha alpha / alpha)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / 40%) ${colorSpace} z alpha x / y)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / 40%) ${colorSpace} alpha alpha alpha / alpha)`); // Testing invalid values. - test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} 10deg y z)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x 10deg z)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x y 10deg)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x y z / 10deg)`, `rgba(0, 0, 0, 0)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} 10deg y z)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x 10deg z)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x y 10deg)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x y z / 10deg)`); // Testing invalid component names - test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} red y)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} r y z)`, `rgba(0, 0, 0, 0)`); - test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} l y z)`, `rgba(0, 0, 0, 0)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} red y)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} r y z)`); + test_invalid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} l y z)`); } </script> </body>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-valid-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-valid-expected.txt index feb3805..612ee9b 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-valid-expected.txt +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-valid-expected.txt
@@ -1,11 +1,19 @@ This is a testharness.js-based test. -Found 586 tests; 13 PASS, 573 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 881 tests; 13 PASS, 868 FAIL, 0 TIMEOUT, 0 NOTRUN. FAIL e.style['color'] = "rgb(from rebeccapurple r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "rgb(from rebeccapurple r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "rgb(from rgb(from rebeccapurple r g b) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "rgb(from color(display-p3 0 1 0) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lab(100% 104.3 -50.9) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lab(0% 104.3 -50.9) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lch(100% 116 334) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lch(0% 116 334) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklab(100% 0.365 -0.16) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklab(0% 0.365 -0.16) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklch(100% 0.399 336.3) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklch(0% 0.399 336.3) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "rgb(from rebeccapurple 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "rgb(from rebeccapurple 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "rgb(from rebeccapurple 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -58,12 +66,31 @@ FAIL e.style['color'] = "rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% 40% 60% / 80%) r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(none none none) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(none none none / none) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% none 60%) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% 40% 60% / none) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hsl(from rebeccapurple h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hsl(from rebeccapurple h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hsl(from hsl(from rebeccapurple h s l) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hsl(from color(display-p3 0 1 0) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lab(100% 104.3 -50.9) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lab(0% 104.3 -50.9) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lch(100% 116 334) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lch(0% 116 334) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklab(100% 0.365 -0.16) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklab(0% 0.365 -0.16) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklch(100% 0.399 336.3) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklch(0% 0.399 336.3) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hsl(from rebeccapurple 0 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hsl(from rebeccapurple 0deg 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hsl(from rebeccapurple 0 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -98,12 +125,34 @@ FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hsl(from rebeccapurple calc(h) calc(s) calc(l))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s l / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple none s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s l / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(none none none) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(none none none / none) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg none 50% / .5) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / none) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(none 20% 50% / .5) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hwb(from rebeccapurple h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hwb(from rebeccapurple h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hwb(from hwb(from rebeccapurple h w b) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hwb(from color(display-p3 0 1 0) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lab(100% 104.3 -50.9) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lab(0% 104.3 -50.9) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lch(100% 116 334) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lch(0% 116 334) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklab(100% 0.365 -0.16) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklab(0% 0.365 -0.16) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklch(100% 0.399 336.3) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklch(0% 0.399 336.3) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hwb(from rebeccapurple 0 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hwb(from rebeccapurple 0deg 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hwb(from rebeccapurple 0 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -138,9 +187,25 @@ FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hwb(from rebeccapurple calc(h) calc(w) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple none w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) h w b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(none none none) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(none none none / none) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg none 50% / .5) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / none) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(none 20% 50% / .5) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(200% 300 400 / 500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(-200% -300 -400 / -500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(from lab(25% 20 50) l a b) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from color(display-p3 0 0 0) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50) 0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -161,15 +226,30 @@ FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l 35 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a 35 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a b / .35)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50) calc(l) calc(a) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(none none none) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(none none none / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% none 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(200% 300 400 / 500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(-200% -300 -400 / -500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(from oklab(25% 20 50) l a b) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from color(display-p3 0 0 0) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50) 0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -190,15 +270,30 @@ FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l 35 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a 35 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a b / .35)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50) calc(l) calc(a) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(none none none) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(none none none / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% none 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" -FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h/ alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(200% 300 400 / 500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(-200% -300 -400 / -500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from lch(from lch(70% 45 30) l c h) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from color(display-p3 0 0 0) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from lab(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -226,6 +321,10 @@ FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 50% 120 400deg / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 50% 120 -400deg / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from lch(70% 45 30) alpha c h / l)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from lch(70% 45 30) l c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from lch(70% 45 30) alpha c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -236,9 +335,22 @@ FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) alpha c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from lch(70% 45 30) calc(l) calc(c) calc(h))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(none none none) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(none none none / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% none 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" -FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h/ alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(200% 300 400 / 500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(-200% -300 -400 / -500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from oklch(from oklch(70% 45 30) l c h) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from color(display-p3 0 0 0) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from oklab(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -266,6 +378,10 @@ FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c 25deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 50% 120 400deg / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 50% 120 -400deg / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from oklch(70% 45 30) alpha c h / l)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from oklch(70% 45 30) alpha c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -276,6 +392,17 @@ FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) alpha c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from oklch(70% 45 30) calc(l) calc(c) calc(h))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(none none none) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(none none none / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% none 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -307,6 +434,14 @@ FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -315,8 +450,27 @@ FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb none none none) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb none none none / none) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 none 0.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / none) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -348,6 +502,14 @@ FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -356,8 +518,27 @@ FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear none none none) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear none none none / none) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 none 0.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / none) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -389,6 +570,14 @@ FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -397,8 +586,27 @@ FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb none none none) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb none none none / none) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 none 0.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / none) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -430,6 +638,14 @@ FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -438,8 +654,27 @@ FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 none none none) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 none none none / none) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 none 0.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / none) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -471,6 +706,14 @@ FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -479,8 +722,27 @@ FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb none none none) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb none none none / none) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 none 0.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / none) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -511,6 +773,17 @@ FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz calc(x) calc(y) calc(z))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz calc(x) calc(y) calc(z) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz none none none) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz none none none / none) xyz x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 none 100) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / none) xyz x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -541,6 +814,17 @@ FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 calc(x) calc(y) calc(z))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 calc(x) calc(y) calc(z) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 none none none) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 none none none / none) xyz-d50 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 none 100) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / none) xyz-d50 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" @@ -571,6 +855,17 @@ FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 calc(x) calc(y) calc(z))" should set the property value assert_not_equals: property should be set got disallowed value "" FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 calc(x) calc(y) calc(z) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 none none none) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 none 100) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" PASS e.style['color'] = "rgb(from var(--bg-color) r g b / 80%)" should set the property value PASS e.style['color'] = "lch(from var(--color) calc(l / 2) c h)" should set the property value PASS e.style['color'] = "rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))" should set the property value
diff --git a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-valid.html b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-valid.html index 2579396..0788641 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-valid.html +++ b/third_party/blink/web_tests/external/wpt/css/css-color/parsing/relative-color-valid.html
@@ -32,8 +32,16 @@ // Test nesting relative colors. test_valid_value(`color`, `rgb(from rgb(from rebeccapurple r g b) r g b)`, `rgb(102, 51, 153)`); - // Testing non-sRGB origin colors to see gamut clipping. - test_valid_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 255, 0)`); + // Testing non-sRGB origin colors to see gamut mapping. + test_valid_value(`color`, `rgb(from color(display-p3 0 1 0) r g b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0). + test_valid_value(`color`, `rgb(from lab(100% 104.3 -50.9) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_valid_value(`color`, `rgb(from lab(0% 104.3 -50.9) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_valid_value(`color`, `rgb(from lch(100% 116 334) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_valid_value(`color`, `rgb(from lch(0% 116 334) r g b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_valid_value(`color`, `rgb(from oklab(100% 0.365 -0.16) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255). + test_valid_value(`color`, `rgb(from oklab(0% 0.365 -0.16) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24). + test_valid_value(`color`, `rgb(from oklch(100% 0.399 336.3) r g b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255). + test_valid_value(`color`, `rgb(from oklch(0% 0.399 336.3) r g b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24). // Testing replacement with 0. test_valid_value(`color`, `rgb(from rebeccapurple 0 0 0)`, `rgb(0, 0, 0)`); @@ -104,6 +112,20 @@ test_valid_value(`color`, `rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)`, `rgb(102, 51, 10)`); test_valid_value(`color`, `rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))`, `rgba(51, 102, 153, 0.8)`); + // Testing with 'none'. + test_valid_value(`color`, `rgb(from rebeccapurple none none none)`, `rgb(0, 0, 0)`); + test_valid_value(`color`, `rgb(from rebeccapurple none none none / none)`, `rgba(0, 0, 0, 0)`); + test_valid_value(`color`, `rgb(from rebeccapurple r g none)`, `rgb(102, 51, 0)`); + test_valid_value(`color`, `rgb(from rebeccapurple r g none / alpha)`, `rgb(102, 51, 0)`); + test_valid_value(`color`, `rgb(from rebeccapurple r g b / none)`, `rgba(102, 51, 153, 0)`); + test_valid_value(`color`, `rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)`, `rgba(51, 102, 0, 0.8)`); + test_valid_value(`color`, `rgb(from rgb(20% 40% 60% / 80%) r g b / none)`, `rgba(51, 102, 153, 0)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_valid_value(`color`, `rgb(from rgb(none none none) r g b)`, `rgb(0, 0, 0)`); + test_valid_value(`color`, `rgb(from rgb(none none none / none) r g b / alpha)`, `rgba(0, 0, 0, 0)`); + test_valid_value(`color`, `rgb(from rgb(20% none 60%) r g b)`, `rgb(51, 0, 153)`); + test_valid_value(`color`, `rgb(from rgb(20% 40% 60% / none) r g b / alpha)`, `rgba(51, 102, 153, 0)`); + // hsl(from ...) @@ -116,8 +138,16 @@ // Test nesting relative colors. test_valid_value(`color`, `hsl(from hsl(from rebeccapurple h s l) h s l)`, `rgb(102, 51, 153)`); - // Testing non-sRGB origin colors to see gamut clipping. - test_valid_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 255, 0)`); + // Testing non-sRGB origin colors to see gamut mapping. + test_valid_value(`color`, `hsl(from color(display-p3 0 1 0) h s l / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0). + test_valid_value(`color`, `hsl(from lab(100% 104.3 -50.9) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_valid_value(`color`, `hsl(from lab(0% 104.3 -50.9) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_valid_value(`color`, `hsl(from lch(100% 116 334) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_valid_value(`color`, `hsl(from lch(0% 116 334) h s l)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_valid_value(`color`, `hsl(from oklab(100% 0.365 -0.16) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255). + test_valid_value(`color`, `hsl(from oklab(0% 0.365 -0.16) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24). + test_valid_value(`color`, `hsl(from oklch(100% 0.399 336.3) h s l)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255). + test_valid_value(`color`, `hsl(from oklch(0% 0.399 336.3) h s l)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24). // Testing replacement with 0. test_valid_value(`color`, `hsl(from rebeccapurple 0 0% 0%)`, `rgb(0, 0, 0)`); @@ -161,6 +191,22 @@ test_valid_value(`color`, `hsl(from rebeccapurple calc(h) calc(s) calc(l))`, `rgb(102, 51, 153)`); test_valid_value(`color`, `hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))`, `rgba(51, 102, 153, 0.8)`); + // Testing with 'none'. + test_valid_value(`color`, `hsl(from rebeccapurple none none none)`, `rgb(0, 0, 0)`); + test_valid_value(`color`, `hsl(from rebeccapurple none none none / none)`, `rgba(0, 0, 0, 0)`); + test_valid_value(`color`, `hsl(from rebeccapurple h s none)`, `rgb(0, 0, 0)`); + test_valid_value(`color`, `hsl(from rebeccapurple h s none / alpha)`, `rgb(0, 0, 0)`); + test_valid_value(`color`, `hsl(from rebeccapurple h s l / none)`, `rgba(102, 51, 153, 0)`); + test_valid_value(`color`, `hsl(from rebeccapurple none s l / alpha)`, `rgb(153, 51, 51)`); + test_valid_value(`color`, `hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)`, `rgba(0, 0, 0, 0.5)`); + test_valid_value(`color`, `hsl(from hsl(120deg 20% 50% / .5) h s l / none)`, `rgba(102, 153, 102, 0)`); + test_valid_value(`color`, `hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)`, `rgba(153, 102, 102, 0.5)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_valid_value(`color`, `hsl(from hsl(none none none) h s l)`, `rgb(0, 0, 0)`); + test_valid_value(`color`, `hsl(from hsl(none none none / none) h s l / alpha)`, `rgba(0, 0, 0, 0)`); + test_valid_value(`color`, `hsl(from hsl(120deg none 50% / .5) h s l)`, `rgb(128, 128, 128)`); + test_valid_value(`color`, `hsl(from hsl(120deg 20% 50% / none) h s l / alpha)`, `rgba(102, 153, 102, 0)`); + test_valid_value(`color`, `hsl(from hsl(none 20% 50% / .5) h s l / alpha)`, `rgba(153, 102, 102, 0.5)`); // hwb(from ...) @@ -173,8 +219,16 @@ // Test nesting relative colors. test_valid_value(`color`, `hwb(from hwb(from rebeccapurple h w b) h w b)`, `rgb(102, 51, 153)`); - // Testing non-sRGB origin colors to see gamut clipping. - test_valid_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 255, 0)`); + // Testing non-sRGB origin colors to see gamut mapping. + test_valid_value(`color`, `hwb(from color(display-p3 0 1 0) h w b / alpha)`, `rgb(0, 249, 66)`); // Naive clip based mapping would give rgb(0, 255, 0). + test_valid_value(`color`, `hwb(from lab(100% 104.3 -50.9) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_valid_value(`color`, `hwb(from lab(0% 104.3 -50.9) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_valid_value(`color`, `hwb(from lch(100% 116 334) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 150, 255). + test_valid_value(`color`, `hwb(from lch(0% 116 334) h w b)`, `rgb(42, 0, 34)`); // Naive clip based mapping would give rgb(90, 0, 76). NOTE: 0% lightness in Lab/LCH does not automatically correspond with sRGB black, + test_valid_value(`color`, `hwb(from oklab(100% 0.365 -0.16) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 92, 255). + test_valid_value(`color`, `hwb(from oklab(0% 0.365 -0.16) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(19, 0, 24). + test_valid_value(`color`, `hwb(from oklch(100% 0.399 336.3) h w b)`, `rgb(255, 255, 255)`); // Naive clip based mapping would give rgb(255, 91, 255). + test_valid_value(`color`, `hwb(from oklch(0% 0.399 336.3) h w b)`, `rgb(0, 0, 0)`); // Naive clip based mapping would give rgb(20, 0, 24). // Testing replacement with 0. test_valid_value(`color`, `hwb(from rebeccapurple 0 0% 0%)`, `rgb(255, 0, 0)`); @@ -218,11 +272,30 @@ test_valid_value(`color`, `hwb(from rebeccapurple calc(h) calc(w) calc(b))`, `rgb(102, 51, 153)`); test_valid_value(`color`, `hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))`, `rgba(51, 102, 153, 0.8)`); + // Testing with 'none'. + test_valid_value(`color`, `hwb(from rebeccapurple none none none)`, `rgb(255, 0, 0)`); + test_valid_value(`color`, `hwb(from rebeccapurple none none none / none)`, `rgba(255, 0, 0, 0)`); + test_valid_value(`color`, `hwb(from rebeccapurple h w none)`, `rgb(153, 51, 255)`); + test_valid_value(`color`, `hwb(from rebeccapurple h w none / alpha)`, `rgb(153, 51, 255)`); + test_valid_value(`color`, `hwb(from rebeccapurple h w b / none)`, `rgba(102, 51, 153, 0)`); + test_valid_value(`color`, `hwb(from rebeccapurple none w b / alpha)`, `rgb(153, 51, 51)`); + test_valid_value(`color`, `hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)`, `rgba(51, 255, 51, 0.5)`); + test_valid_value(`color`, `hwb(from hwb(120deg 20% 50% / .5) h w b / none)`, `rgba(51, 128, 51, 0)`); + test_valid_value(`color`, `hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)`, `rgba(128, 51, 51, 0.5)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_valid_value(`color`, `hwb(from hwb(none none none) h w b)`, `rgb(255, 0, 0)`); + test_valid_value(`color`, `hwb(from hwb(none none none / none) h w b / alpha)`, `rgba(255, 0, 0, 0)`); + test_valid_value(`color`, `hwb(from hwb(120deg none 50% / .5) h w b)`, `rgb(0, 128, 0)`); + test_valid_value(`color`, `hwb(from hwb(120deg 20% 50% / none) h w b / alpha)`, `rgba(51, 128, 51, 0)`); + test_valid_value(`color`, `hwb(from hwb(none 20% 50% / .5) h w b / alpha)`, `rgba(128, 51, 51, 0.5)`); + for (const colorSpace of [ "lab", "oklab" ]) { // Testing no modifications. test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l a b)`, `${colorSpace}(25% 20 50)`); test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l a b / alpha)`, `${colorSpace}(25% 20 50)`); test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l a b / alpha)`, `${colorSpace}(25% 20 50 / 0.4)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(200% 300 400 / 500%) l a b / alpha)`, `${colorSpace}(200% 300 400)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(-200% -300 -400 / -500%) l a b / alpha)`, `${colorSpace}(0% -300 -400 / 0)`); // Test nesting relative colors. test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(from ${colorSpace}(25% 20 50) l a b) l a b)`, `${colorSpace}(25% 20 50)`); @@ -251,6 +324,8 @@ test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l 35 b / alpha)`, `${colorSpace}(25% 35 50 / 0.4)`); test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l a 35 / alpha)`, `${colorSpace}(25% 20 35 / 0.4)`); test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l a b / .35)`, `${colorSpace}(25% 20 50 / 0.35)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) 200% 300 400 / 500)`, `${colorSpace}(200% 300 400)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) -200% -300 -400 / -500)`, `${colorSpace}(0% -300 -400 / 0)`); // Testing valid permutation (types match). test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l b a)`, `${colorSpace}(25% 50 20)`); @@ -261,6 +336,20 @@ // Testing with calc(). test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) calc(l) calc(a) calc(b))`, `${colorSpace}(25% 20 50)`); test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))`, `${colorSpace}(25% 20 50 / 0.4)`); + + // Testing with 'none'. + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) none none none)`, `${colorSpace}(none none none)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) none none none / none)`, `${colorSpace}(none none none / none)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l a none)`, `${colorSpace}(25% 20 none)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l a none / alpha)`, `${colorSpace}(25% 20 none)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50) l a b / none)`, `${colorSpace}(25% 20 50 / none)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l a none / alpha)`, `${colorSpace}(25% 20 none / 0.4)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / 40%) l a b / none)`, `${colorSpace}(25% 20 50 / none)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(none none none) l a b)`, `${colorSpace}(0% 0 0)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(none none none / none) l a b / alpha)`, `${colorSpace}(0% 0 0 / 0)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% none 50) l a b)`, `${colorSpace}(25% 0 50)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(25% 20 50 / none) l a b / alpha)`, `${colorSpace}(25% 20 50 / 0)`); } for (const colorSpace of [ "lch", "oklch" ]) { @@ -269,12 +358,14 @@ // Testing no modifications. test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) l c h)`, `${colorSpace}(70% 45 30)`); test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) l c h / alpha)`, `${colorSpace}(70% 45 30)`); - test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c h/ alpha)`, `${colorSpace}(70% 45 30 / 0.4)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c h / alpha)`, `${colorSpace}(70% 45 30 / 0.4)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(200% 300 400 / 500%) l c h / alpha)`, `${colorSpace}(200% 300 40)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(-200% -300 -400 / -500%) l c h / alpha)`, `${colorSpace}(0% 0 320 / 0)`); // Test nesting relative colors. test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(from ${colorSpace}(70% 45 30) l c h) l c h)`, `${colorSpace}(70% 45 30)`); - // Testing non-sRGB origin colors to see gamut clipping. + // Testing non-sRGB origin colors (no gamut mapping will happen since the destination is not a bounded RGB color space). test_valid_value(`color`, `${colorSpace}(from color(display-p3 0 0 0) l c h / alpha)`, `${colorSpace}(0% 0 0)`); test_valid_value(`color`, `${colorSpace}(from ${rectangularForm}(70% 45 30) l c h / alpha)`, `${colorSpace}(70% 54.08327 33.690067)`); @@ -305,6 +396,10 @@ test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c 25 / alpha)`, `${colorSpace}(70% 45 25 / 0.4)`); test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c 25deg / alpha)`, `${colorSpace}(70% 45 25 / 0.4)`); test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c h / .25)`, `${colorSpace}(70% 45 30 / 0.25)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) 200% 300 400 / 500)`, `${colorSpace}(200% 300 40)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) -200% -300 -400 / -500)`, `${colorSpace}(0% 0 320 / 0)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) 50% 120 400deg / 500)`, `${colorSpace}(50% 120 40)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) 50% 120 -400deg / -500)`, `${colorSpace}(50% 120 320 / 0)`); // Testing valid permutation (types match). // NOTE: 'c' is a vaild hue, as hue is <angle>|<number>. @@ -320,6 +415,20 @@ // Testing with calc(). test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) calc(l) calc(c) calc(h))`, `${colorSpace}(70% 45 30)`); test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))`, `${colorSpace}(70% 45 30 / 0.4)`); + + // Testing with 'none'. + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) none none none)`, `${colorSpace}(none none none)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) none none none / none)`, `${colorSpace}(none none none / none)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) l c none)`, `${colorSpace}(70% 45 none)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) l c none / alpha)`, `${colorSpace}(70% 45 none)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30) l c h / none)`, `${colorSpace}(70% 45 30 / none)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c none / alpha)`, `${colorSpace}(70% 45 none / 0.4)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / 40%) l c h / none)`, `${colorSpace}(70% 45 30 / none)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(none none none) l c h)`, `${colorSpace}(0% 0 0)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(none none none / none) l c h / alpha)`, `${colorSpace}(0% 0 0 / 0)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% none 30) l c h)`, `${colorSpace}(70% 0 30)`); + test_valid_value(`color`, `${colorSpace}(from ${colorSpace}(70% 45 30 / none) l c h / alpha)`, `${colorSpace}(70% 45 30 / 0)`); } for (const colorSpace of [ "srgb", "srgb-linear", "a98-rgb", "rec2020", "prophoto-rgb" ]) { @@ -361,6 +470,14 @@ test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r g 20% / alpha)`, `color(${colorSpace} 0.7 0.5 0.2 / 0.4)`); test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r g b / 0.2)`, `color(${colorSpace} 0.7 0.5 0.3 / 0.2)`); test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r g b / 20%)`, `color(${colorSpace} 0.7 0.5 0.3 / 0.2)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} 2 3 4)`, `color(${colorSpace} 2 3 4)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} 2 3 4 / 5)`, `color(${colorSpace} 2 3 4)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} -2 -3 -4)`, `color(${colorSpace} -2 -3 -4)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} -2 -3 -4 / -5)`, `color(${colorSpace} -2 -3 -4 / 0)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} 200% 300% 400%)`, `color(${colorSpace} 2 3 4)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} 200% 300% 400% / 500%)`, `color(${colorSpace} 2 3 4)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} -200% -300% -400%)`, `color(${colorSpace} -2 -3 -4)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} -200% -300% -400% / -500%)`, `color(${colorSpace} -2 -3 -4 / 0)`); // Testing valid permutation (types match). test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} g b r)`, `color(${colorSpace} 0.5 0.3 0.7)`); @@ -372,9 +489,33 @@ test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r r r / r)`, `color(${colorSpace} 0.7 0.7 0.7 / 0.7)`); test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} alpha alpha alpha / alpha)`, `color(${colorSpace} 0.4 0.4 0.4 / 0.4)`); + // Testing out of gamut components. + test_valid_value(`color`, `color(from color(${colorSpace} 1.7 1.5 1.3) ${colorSpace} r g b)`, `color(${colorSpace} 1.7 1.5 1.3)`); + test_valid_value(`color`, `color(from color(${colorSpace} 1.7 1.5 1.3) ${colorSpace} r g b / alpha)`, `color(${colorSpace} 1.7 1.5 1.3)`); + test_valid_value(`color`, `color(from color(${colorSpace} 1.7 1.5 1.3 / 140%) ${colorSpace} r g b)`, `color(${colorSpace} 1.7 1.5 1.3)`); + test_valid_value(`color`, `color(from color(${colorSpace} 1.7 1.5 1.3 / 140%) ${colorSpace} r g b / alpha)`, `color(${colorSpace} 1.7 1.5 1.3)`); + test_valid_value(`color`, `color(from color(${colorSpace} -0.7 -0.5 -0.3) ${colorSpace} r g b)`, `color(${colorSpace} -0.7 -0.5 -0.3)`); + test_valid_value(`color`, `color(from color(${colorSpace} -0.7 -0.5 -0.3) ${colorSpace} r g b / alpha)`, `color(${colorSpace} -0.7 -0.5 -0.3)`); + test_valid_value(`color`, `color(from color(${colorSpace} -0.7 -0.5 -0.3 / -40%) ${colorSpace} r g b)`, `color(${colorSpace} -0.7 -0.5 -0.3)`); + test_valid_value(`color`, `color(from color(${colorSpace} -0.7 -0.5 -0.3 / -40%) ${colorSpace} r g b / alpha)`, `color(${colorSpace} -0.7 -0.5 -0.3 / 0)`); + // Testing with calc(). test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} calc(r) calc(g) calc(b))`, `color(${colorSpace} 0.7 0.5 0.3)`); test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} calc(r) calc(g) calc(b) / calc(alpha))`, `color(${colorSpace} 0.7 0.5 0.3 / 0.4)`); + + // Testing with 'none'. + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} none none none)`, `color(${colorSpace} none none none)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} none none none / none)`, `color(${colorSpace} none none none / none)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r g none)`, `color(${colorSpace} 0.7 0.5 none)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r g none / alpha)`, `color(${colorSpace} 0.7 0.5 none)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3) ${colorSpace} r g b / none)`, `color(${colorSpace} 0.7 0.5 0.3 / none)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r g none / alpha)`, `color(${colorSpace} 0.7 0.5 none / 0.4)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / 40%) ${colorSpace} r g b / none)`, `color(${colorSpace} 0.7 0.5 0.3 / none)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_valid_value(`color`, `color(from color(${colorSpace} none none none) ${colorSpace} r g b)`, `color(${colorSpace} 0 0 0)`); + test_valid_value(`color`, `color(from color(${colorSpace} none none none / none) ${colorSpace} r g b / alpha)`, `color(${colorSpace} 0 0 0 / 0)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 none 0.3) ${colorSpace} r g b)`, `color(${colorSpace} 0.7 0 0.3)`); + test_valid_value(`color`, `color(from color(${colorSpace} 0.7 0.5 0.3 / none) ${colorSpace} r g b / alpha)`, `color(${colorSpace} 0.7 0.5 0.3 / 0)`); } for (const colorSpace of [ "xyz", "xyz-d50", "xyz-d65" ]) { @@ -391,7 +532,7 @@ // Testing replacement with 0. test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} 0 0 0)`, `color(${resultColorSpace} 0 0 0)`); - test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} 0 0 0 / 0)`, `color(${resultColorSpace} 0 0 0 / 0)`); + test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} 0 0 0 / 0)`, `color(${resultColorSpace} 0 0 0 / 0)`); test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} 0 y z / alpha)`, `color(${resultColorSpace} 0 -20.5 100)`); test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x 0 z / alpha)`, `color(${resultColorSpace} 7 0 100)`); test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x y 0 / alpha)`, `color(${resultColorSpace} 7 -20.5 0)`); @@ -421,6 +562,20 @@ // Testing with calc(). test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} calc(x) calc(y) calc(z))`, `color(${resultColorSpace} 7 -20.5 100)`); test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / 40%) ${colorSpace} calc(x) calc(y) calc(z) / calc(alpha))`, `color(${resultColorSpace} 7 -20.5 100 / 0.4)`); + + // Testing with 'none'. + test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} none none none)`, `color(${resultColorSpace} none none none)`); + test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} none none none / none)`, `color(${resultColorSpace} none none none / none)`); + test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x y none)`, `color(${resultColorSpace} 7 -20.5 none)`); + test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x y none / alpha)`, `color(${resultColorSpace} 7 -20.5 none)`); + test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100) ${colorSpace} x y z / none)`, `color(${resultColorSpace} 7 -20.5 100 / none)`); + test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / 40%) ${colorSpace} x y none / alpha)`, `color(${resultColorSpace} 7 -20.5 none / 0.4)`); + test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / 40%) ${colorSpace} x y z / none)`, `color(${resultColorSpace} 7 -20.5 100 / none)`); + // FIXME: Clarify with spec editors if 'none' should pass through to the constants. + test_valid_value(`color`, `color(from color(${colorSpace} none none none) ${colorSpace} x y z)`, `color(${resultColorSpace} 0 0 0)`); + test_valid_value(`color`, `color(from color(${colorSpace} none none none / none) ${colorSpace} x y z / alpha)`, `color(${resultColorSpace} 0 0 0 / 0)`); + test_valid_value(`color`, `color(from color(${colorSpace} 7 none 100) ${colorSpace} x y z)`, `color(${resultColorSpace} 7 0 100)`); + test_valid_value(`color`, `color(from color(${colorSpace} 7 -20.5 100 / none) ${colorSpace} x y z / alpha)`, `color(${resultColorSpace} 7 -20.5 100 / 0)`); } // Spec Examples
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-shadow-dom.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-shadow-dom.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-shadow-dom.tentative.html rename to third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/container-for-shadow-dom.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-002.tentative-ref.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-002-ref.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-002.tentative-ref.html rename to third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-002-ref.html
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-002.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-002.html similarity index 97% rename from third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-002.tentative.html rename to third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-002.html index e46d25c..a41bc43 100644 --- a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-002.tentative.html +++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-002.html
@@ -1,7 +1,7 @@ <!DOCTYPE html> <title>CSS Container Queries Test: Container for pseudo elements</title> <link rel="help" href="https://github.com/w3c/csswg-drafts/issues/6711"> -<link rel="match" href="pseudo-elements-002.tentative-ref.html"> +<link rel="match" href="pseudo-elements-002-ref.html"> <style> .container { container-type: inline-size; }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-003.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-003.html similarity index 100% rename from third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-003.tentative.html rename to third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/pseudo-elements-003.html
diff --git a/third_party/blink/web_tests/external/wpt/html/interaction/focus/processing-model/focus-fixup-rule-one-no-dialogs.html b/third_party/blink/web_tests/external/wpt/html/interaction/focus/processing-model/focus-fixup-rule-one-no-dialogs.html index 31b1919..2413fe26 100644 --- a/third_party/blink/web_tests/external/wpt/html/interaction/focus/processing-model/focus-fixup-rule-one-no-dialogs.html +++ b/third_party/blink/web_tests/external/wpt/html/interaction/focus/processing-model/focus-fixup-rule-one-no-dialogs.html
@@ -31,7 +31,7 @@ assert_not_equals(document.activeElement, button, "After disabling, the button must no longer be focused"); assert_equals(document.activeElement, document.body, "After disabling, the body must be focused"); -}, "Disabling the active element (making it expressly inert)"); +}, "Disabling the active element (making it inert)"); test(() => { const button = document.querySelector("#button2");
diff --git a/third_party/blink/web_tests/external/wpt/inert/dynamic-inert-on-focused-element.tentative.html b/third_party/blink/web_tests/external/wpt/inert/dynamic-inert-on-focused-element.tentative.html index 42b6e219..0ddf5a9 100644 --- a/third_party/blink/web_tests/external/wpt/inert/dynamic-inert-on-focused-element.tentative.html +++ b/third_party/blink/web_tests/external/wpt/inert/dynamic-inert-on-focused-element.tentative.html
@@ -3,7 +3,7 @@ <title>Dynamic inertness on focused element</title> <link rel="author" title="Oriol Brufau" href="mailto:obrufau@igalia.com"> <link rel="help" href="https://html.spec.whatwg.org/multipage/interaction.html#focus-fixup-rule"> -<meta name="assert" content="If a focused element becomes expressly inert, it stops being focused."> +<meta name="assert" content="If a focused element becomes inert, it stops being focused."> <div id="log"></div> <div class="test-wrapper" data-name="<input> that gets 'inert' attribute">
diff --git a/third_party/blink/web_tests/external/wpt/resources/idlharness.js b/third_party/blink/web_tests/external/wpt/resources/idlharness.js index 611a26f1..53ca06d 100644 --- a/third_party/blink/web_tests/external/wpt/resources/idlharness.js +++ b/third_party/blink/web_tests/external/wpt/resources/idlharness.js
@@ -817,6 +817,13 @@ test(function () { const partialExposure = exposure_set(parsed_idl); const memberExposure = exposure_set(this.members[parsed_idl.name]); + if (memberExposure === "*") { + return; + } + if (partialExposure === "*") { + throw new IdlHarnessError( + `Partial ${parsed_idl.name} ${parsed_idl.type} is exposed everywhere, the original ${parsed_idl.type} is not.`); + } partialExposure.forEach(name => { if (!memberExposure || !memberExposure.has(name)) { throw new IdlHarnessError( @@ -1593,7 +1600,7 @@ if (this.is_callback()) { throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on non-interface " + this.name); } - if (!this.exposureSet.has("Window")) { + if (!(this.exposureSet === "*" || this.exposureSet.has("Window"))) { throw new IdlHarnessError("Invalid IDL: LegacyWindowAlias extended attribute on " + this.name + " which is not exposed in Window"); } // TODO: when testing of [LegacyNoInterfaceObject] interfaces is supported,
diff --git a/third_party/blink/web_tests/external/wpt/streams/readable-streams/global.html b/third_party/blink/web_tests/external/wpt/streams/readable-streams/global.html deleted file mode 100644 index 08665d31..0000000 --- a/third_party/blink/web_tests/external/wpt/streams/readable-streams/global.html +++ /dev/null
@@ -1,162 +0,0 @@ -<!doctype html> -<meta charset="utf-8"> -<title>Ensure Stream objects are created in expected globals. </title> - -<script src="/resources/testharness.js"></script> -<script src="/resources/testharnessreport.js"></script> - -<body></body> -<script> -// These tests are loosely derived from Gecko's readable-stream-globals.js, -// which is a test case designed around the JS Streams implementation. -// -// Unlike in JS Streams, where function calls switch realms and change -// the resulting global of the resulting objects, in WebIDL streams, -// the global of an object is (currently underspecified, but) intended -// to be the "Relevant Global" of the 'this' object. -// -// See: -// https://html.spec.whatwg.org/multipage/webappapis.html#relevant -// https://github.com/whatwg/streams/issues/1213 -"use strict" - -const iframe = document.createElement("iframe") -document.body.append(iframe) - -const otherGlobal = iframe.contentWindow; -const OtherReadableStream = otherGlobal.ReadableStream -const OtherReadableStreamDefaultReader = otherGlobal.ReadableStreamDefaultReader; -const OtherReadableStreamDefaultController = otherGlobal.ReadableStreamDefaultController; - -promise_test(async () => { - - // Controllers - let controller; - let otherController; - - // Get Stream Prototypes and controllers. - let streamController; - let stream = new ReadableStream({start(c) { streamController = c; }}); - - const callReaderThisGlobal = OtherReadableStream.prototype.getReader.call(stream); - const newReaderOtherGlobal = new OtherReadableStreamDefaultReader(new ReadableStream()); - - // Relevant Global Checking. - assert_equals(callReaderThisGlobal instanceof ReadableStreamDefaultReader, true, "reader was created in this global (.call)"); - assert_equals(newReaderOtherGlobal instanceof ReadableStreamDefaultReader, false, "reader was created in other global (new)"); - - assert_equals(callReaderThisGlobal instanceof OtherReadableStreamDefaultReader, false, "reader isn't coming from other global (.call)" ); - assert_equals(newReaderOtherGlobal instanceof OtherReadableStreamDefaultReader, true, "reader isn't coming from other global (new)"); - - assert_equals(otherController instanceof ReadableStreamDefaultController, false, "otherController should come from other gloal") - - - const request = callReaderThisGlobal.read(); - assert_equals(request instanceof Promise, true, "Promise comes from this global"); - - streamController.close(); - const requestResult = await request; - assert_equals(requestResult instanceof Object, true, "returned object comes from this global"); -}, "Stream objects created in expected globals") - -promise_test(async () => { - const stream = new ReadableStream(); - const otherReader = new OtherReadableStreamDefaultReader(stream); - const cancelPromise = ReadableStreamDefaultReader.prototype.cancel.call(otherReader); - assert_equals(cancelPromise instanceof Promise, true, "Cancel promise comes from the same global as the stream"); - assert_equals(await cancelPromise, undefined, "Cancel promise resolves to undefined"); -}, "Cancel promise is created in same global as stream") - -// Refresh the streams and controllers. -function getFreshInstances() { - let controller; - let otherController; - let stream = new ReadableStream({ - start(c) { - controller = c; - } - }); - - new OtherReadableStream({ - start(c) { - otherController = c; - } - }); - - return {stream, controller, otherController} -} - - -promise_test(async () => { - // Test closed promise on reader from another global (connected to a this-global stream) - const {stream, controller, otherController} = getFreshInstances(); - - const otherReader = new OtherReadableStreamDefaultReader(stream); - const closedPromise = otherReader.closed; - assert_equals(closedPromise instanceof otherGlobal.Promise, true, "Closed promise in other global."); -}, "Closed Promise in correct global"); - -promise_test(async () => { - const {stream, controller, otherController} = getFreshInstances(); - - const otherReader = OtherReadableStream.prototype.getReader.call(stream); - assert_equals(otherReader instanceof ReadableStreamDefaultReader, true, "Reader comes from this global") - const request = otherReader.read(); - assert_equals(request instanceof Promise, true, "Promise still comes from stream's realm (this realm)"); - otherController.close.call(controller); - assert_equals((await request) instanceof otherGlobal.Object, true, "Object comes from other realm"); -}, "Reader objects in correct global"); - - -promise_test(async () => { - const {stream, controller, otherController} = getFreshInstances(); - assert_equals(controller.desiredSize, 1, "Desired size is expected"); - Object.defineProperty(controller, "desiredSize", - Object.getOwnPropertyDescriptor(OtherReadableStreamDefaultController.prototype, "desiredSize")); - assert_equals(controller.desiredSize, 1, "Grafting getter from other prototype still returns desired size"); -}, "Desired size can be grafted from one prototype to another"); - -promise_test(async () => { - const {stream, controller, otherController} = getFreshInstances(); - - // Make sure the controller close method returns the correct TypeError - const enqueuedError = { name: "enqueuedError" }; - controller.error(enqueuedError); - - assert_throws_js(TypeError, () => controller.close(), "Current Global controller"); - assert_throws_js(otherGlobal.TypeError, () => otherController.close.call(controller), "Other global controller"); -}, "Closing errored stream throws object in appropriate global") - -promise_test(async () => { - const {otherController} = getFreshInstances(); - // We can enqueue chunks from multiple globals - const chunk = { name: "chunk" }; - - let controller; - const stream = new ReadableStream({ start(c) { controller = c; } }, { size() {return 1} }); - otherController.enqueue.call(controller, chunk); - otherController.enqueue.call(controller, new otherGlobal.Uint8Array(10)); - controller.enqueue(new otherGlobal.Uint8Array(10)); -}, "Can enqueue chunks from multiple globals") - -promise_test(async () => { - const {stream, controller, otherController} = getFreshInstances(); - const chunk = { name: "chunk" }; - - // We get the correct type errors out of a closed stream. - controller.close(); - assert_throws_js(TypeError, () => controller.enqueue(new otherGlobal.Uint8Array(10))); - assert_throws_js(otherGlobal.TypeError, () => otherController.enqueue.call(controller, chunk)); - assert_throws_js(otherGlobal.TypeError, () => otherController.enqueue.call(controller, new otherGlobal.Uint8Array(10))); -}, "Correct errors and globals for closed streams"); - - -promise_test(async () => { - const {stream, controller, otherController} = getFreshInstances(); - // Branches out of tee are in the correct global - - const [branch1, branch2] = otherGlobal.ReadableStream.prototype.tee.call(stream); - assert_equals(branch1 instanceof ReadableStream, true, "Branch created in this global (as stream is in this global)"); - assert_equals(branch2 instanceof ReadableStream, true, "Branch created in this global (as stream is in this global)"); -}, "Tee Branches in correct global"); -</script>
diff --git a/third_party/blink/web_tests/external/wpt/streams/resources/test-utils.js b/third_party/blink/web_tests/external/wpt/streams/resources/test-utils.js index 88a671b..1c932f1 100644 --- a/third_party/blink/web_tests/external/wpt/streams/resources/test-utils.js +++ b/third_party/blink/web_tests/external/wpt/streams/resources/test-utils.js
@@ -48,9 +48,9 @@ }; self.garbageCollect = async () => { - if (self.testUtils?.gc) { - // https://testutils.spec.whatwg.org/#the-testutils-object - await testUtils.gc(); + if (self.TestUtils?.gc) { + // https://testutils.spec.whatwg.org/#the-testutils-namespace + await TestUtils.gc(); } else if (self.gc) { // Use --expose_gc for V8 (and Node.js) // to pass this flag at chrome launch use: --js-flags="--expose-gc"
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-computed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-computed-expected.txt new file mode 100644 index 0000000..d290173 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-computed-expected.txt
@@ -0,0 +1,407 @@ +This is a testharness.js-based test. +Found 403 tests; 27 PASS, 376 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS Property color value 'currentcolor' +PASS Property color value 'transparent' +PASS Property color value 'red' +PASS Property color value 'magenta' +PASS Property color value '#234' +PASS Property color value '#FEDCBA' +PASS Property color value 'rgb(2, 3, 4)' +PASS Property color value 'rgb(100%, 0%, 0%)' +PASS Property color value 'rgba(2, 3, 4, 0.5)' +PASS Property color value 'rgba(2, 3, 4, 50%)' +PASS Property color value 'hsl(120, 100%, 50%)' +PASS Property color value 'hsla(120, 100%, 50%, 0.25)' +PASS Property color value 'rgb(-2, 3, 4)' +PASS Property color value 'rgb(100, 200, 300)' +PASS Property color value 'rgb(20, 10, 0, -10)' +PASS Property color value 'rgb(100%, 200%, 300%)' +FAIL Property color value 'rgb(none none none)' assert_true: 'rgb(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(none none none / none)' assert_true: 'rgb(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(128 none none)' assert_true: 'rgb(128 none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(128 none none / none)' assert_true: 'rgb(128 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(none none none / .5)' assert_true: 'rgb(none none none / .5)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(20% none none)' assert_true: 'rgb(20% none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(20% none none / none)' assert_true: 'rgb(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(none none none / 50%)' assert_true: 'rgb(none none none / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none)' assert_true: 'rgba(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none / none)' assert_true: 'rgba(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(128 none none)' assert_true: 'rgba(128 none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(128 none none / none)' assert_true: 'rgba(128 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none / .5)' assert_true: 'rgba(none none none / .5)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(20% none none)' assert_true: 'rgba(20% none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(20% none none / none)' assert_true: 'rgba(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none / 50%)' assert_true: 'rgba(none none none / 50%)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 30% 50%)' +PASS Property color value 'hsl(120 30% 50% / 0.5)' +FAIL Property color value 'hsl(none none none)' assert_true: 'hsl(none none none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(0 0% 0%)' +FAIL Property color value 'hsl(none none none / none)' assert_true: 'hsl(none none none / none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(0 0% 0% / 0)' +FAIL Property color value 'hsla(none none none)' assert_true: 'hsla(none none none)' is a supported value for color. expected true got false +PASS Property color value 'hsla(0 0% 0%)' +FAIL Property color value 'hsla(none none none / none)' assert_true: 'hsla(none none none / none)' is a supported value for color. expected true got false +PASS Property color value 'hsla(0 0% 0% / 0)' +FAIL Property color value 'hsl(120 none none)' assert_true: 'hsl(120 none none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 0% 0%)' +FAIL Property color value 'hsl(120 80% none)' assert_true: 'hsl(120 80% none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 80% 0%)' +FAIL Property color value 'hsl(120 none 50%)' assert_true: 'hsl(120 none 50%)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 0% 50%)' +FAIL Property color value 'hsl(120 100% 50% / none)' assert_true: 'hsl(120 100% 50% / none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 100% 50% / 0)' +FAIL Property color value 'hsl(none 100% 50%)' assert_true: 'hsl(none 100% 50%)' is a supported value for color. expected true got false +PASS Property color value 'hsl(0 100% 50%)' +FAIL Property color value 'hwb(120 30% 50%)' assert_true: 'hwb(120 30% 50%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 30% 50% / 0.5)' assert_true: 'hwb(120 30% 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(none none none)' assert_true: 'hwb(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(0 0% 0%)' assert_true: 'hwb(0 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(none none none / none)' assert_true: 'hwb(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(0 0% 0% / 0)' assert_true: 'hwb(0 0% 0% / 0)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 none none)' assert_true: 'hwb(120 none none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 0% 0%)' assert_true: 'hwb(120 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 80% none)' assert_true: 'hwb(120 80% none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 80% 0%)' assert_true: 'hwb(120 80% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 none 50%)' assert_true: 'hwb(120 none 50%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 0% 50%)' assert_true: 'hwb(120 0% 50%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 30% 50% / none)' assert_true: 'hwb(120 30% 50% / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 30% 50% / 0)' assert_true: 'hwb(120 30% 50% / 0)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(none 100% 50% / none)' assert_true: 'hwb(none 100% 50% / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(0 100% 50% / 0)' assert_true: 'hwb(0 100% 50% / 0)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0% 0% 0%)' assert_true: 'color(srgb 0% 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 10% 10% 10%)' assert_true: 'color(srgb 10% 10% 10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb .2 .2 25%)' assert_true: 'color(srgb .2 .2 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0 0 0 / 1)' assert_true: 'color(srgb 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0% 0 0 / 0.5)' assert_true: 'color(srgb 0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 20% 0 10/0.5)' assert_true: 'color(srgb 20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 20% 0 10/50%)' assert_true: 'color(srgb 20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 400% 0 10/50%)' assert_true: 'color(srgb 400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50% -160 160)' assert_true: 'color(srgb 50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50% -200 200)' assert_true: 'color(srgb 50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0 0 0 / -10%)' assert_true: 'color(srgb 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0 0 0 / 110%)' assert_true: 'color(srgb 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0 0 0 / 300%)' assert_true: 'color(srgb 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50% -200)' assert_true: 'color(srgb 50% -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50%)' assert_true: 'color(srgb 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb)' assert_true: 'color(srgb)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50% -200 / 0.5)' assert_true: 'color(srgb 50% -200 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50% / 0.5)' assert_true: 'color(srgb 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb / 0.5)' assert_true: 'color(srgb / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200 200 200)' assert_true: 'color(srgb 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200 200 200 / 200)' assert_true: 'color(srgb 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb -200 -200 -200)' assert_true: 'color(srgb -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb -200 -200 -200 / -200)' assert_true: 'color(srgb -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200% 200% 200%)' assert_true: 'color(srgb 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200% 200% 200% / 200%)' assert_true: 'color(srgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb -200% -200% -200% / -200%)' assert_true: 'color(srgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb none none none / none)' assert_true: 'color(srgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb none none none)' assert_true: 'color(srgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 10% none none / none)' assert_true: 'color(srgb 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb none none none / 0.5)' assert_true: 'color(srgb none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0 0 0 / none)' assert_true: 'color(srgb 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0% 0% 0%)' assert_true: 'color(srgb-linear 0% 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 10% 10% 10%)' assert_true: 'color(srgb-linear 10% 10% 10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear .2 .2 25%)' assert_true: 'color(srgb-linear .2 .2 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0 0 0 / 1)' assert_true: 'color(srgb-linear 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0% 0 0 / 0.5)' assert_true: 'color(srgb-linear 0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 20% 0 10/0.5)' assert_true: 'color(srgb-linear 20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 20% 0 10/50%)' assert_true: 'color(srgb-linear 20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 400% 0 10/50%)' assert_true: 'color(srgb-linear 400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50% -160 160)' assert_true: 'color(srgb-linear 50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50% -200 200)' assert_true: 'color(srgb-linear 50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0 0 0 / -10%)' assert_true: 'color(srgb-linear 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0 0 0 / 110%)' assert_true: 'color(srgb-linear 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0 0 0 / 300%)' assert_true: 'color(srgb-linear 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50% -200)' assert_true: 'color(srgb-linear 50% -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50%)' assert_true: 'color(srgb-linear 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear)' assert_true: 'color(srgb-linear)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50% -200 / 0.5)' assert_true: 'color(srgb-linear 50% -200 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50% / 0.5)' assert_true: 'color(srgb-linear 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear / 0.5)' assert_true: 'color(srgb-linear / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200 200 200)' assert_true: 'color(srgb-linear 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200 200 200 / 200)' assert_true: 'color(srgb-linear 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear -200 -200 -200)' assert_true: 'color(srgb-linear -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear -200 -200 -200 / -200)' assert_true: 'color(srgb-linear -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200% 200% 200%)' assert_true: 'color(srgb-linear 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200% 200% 200% / 200%)' assert_true: 'color(srgb-linear 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear -200% -200% -200% / -200%)' assert_true: 'color(srgb-linear -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear none none none / none)' assert_true: 'color(srgb-linear none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear none none none)' assert_true: 'color(srgb-linear none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 10% none none / none)' assert_true: 'color(srgb-linear 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear none none none / 0.5)' assert_true: 'color(srgb-linear none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0 0 0 / none)' assert_true: 'color(srgb-linear 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0% 0% 0%)' assert_true: 'color(a98-rgb 0% 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 10% 10% 10%)' assert_true: 'color(a98-rgb 10% 10% 10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb .2 .2 25%)' assert_true: 'color(a98-rgb .2 .2 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0 0 0 / 1)' assert_true: 'color(a98-rgb 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0% 0 0 / 0.5)' assert_true: 'color(a98-rgb 0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 20% 0 10/0.5)' assert_true: 'color(a98-rgb 20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 20% 0 10/50%)' assert_true: 'color(a98-rgb 20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 400% 0 10/50%)' assert_true: 'color(a98-rgb 400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50% -160 160)' assert_true: 'color(a98-rgb 50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50% -200 200)' assert_true: 'color(a98-rgb 50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0 0 0 / -10%)' assert_true: 'color(a98-rgb 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0 0 0 / 110%)' assert_true: 'color(a98-rgb 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0 0 0 / 300%)' assert_true: 'color(a98-rgb 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50% -200)' assert_true: 'color(a98-rgb 50% -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50%)' assert_true: 'color(a98-rgb 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb)' assert_true: 'color(a98-rgb)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50% -200 / 0.5)' assert_true: 'color(a98-rgb 50% -200 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50% / 0.5)' assert_true: 'color(a98-rgb 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb / 0.5)' assert_true: 'color(a98-rgb / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200 200 200)' assert_true: 'color(a98-rgb 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200 200 200 / 200)' assert_true: 'color(a98-rgb 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb -200 -200 -200)' assert_true: 'color(a98-rgb -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb -200 -200 -200 / -200)' assert_true: 'color(a98-rgb -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200% 200% 200%)' assert_true: 'color(a98-rgb 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200% 200% 200% / 200%)' assert_true: 'color(a98-rgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb -200% -200% -200% / -200%)' assert_true: 'color(a98-rgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb none none none / none)' assert_true: 'color(a98-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb none none none)' assert_true: 'color(a98-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 10% none none / none)' assert_true: 'color(a98-rgb 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb none none none / 0.5)' assert_true: 'color(a98-rgb none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0 0 0 / none)' assert_true: 'color(a98-rgb 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0% 0% 0%)' assert_true: 'color(rec2020 0% 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 10% 10% 10%)' assert_true: 'color(rec2020 10% 10% 10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 .2 .2 25%)' assert_true: 'color(rec2020 .2 .2 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0 0 0 / 1)' assert_true: 'color(rec2020 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0% 0 0 / 0.5)' assert_true: 'color(rec2020 0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 20% 0 10/0.5)' assert_true: 'color(rec2020 20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 20% 0 10/50%)' assert_true: 'color(rec2020 20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 400% 0 10/50%)' assert_true: 'color(rec2020 400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50% -160 160)' assert_true: 'color(rec2020 50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50% -200 200)' assert_true: 'color(rec2020 50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0 0 0 / -10%)' assert_true: 'color(rec2020 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0 0 0 / 110%)' assert_true: 'color(rec2020 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0 0 0 / 300%)' assert_true: 'color(rec2020 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50% -200)' assert_true: 'color(rec2020 50% -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50%)' assert_true: 'color(rec2020 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020)' assert_true: 'color(rec2020)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50% -200 / 0.5)' assert_true: 'color(rec2020 50% -200 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50% / 0.5)' assert_true: 'color(rec2020 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 / 0.5)' assert_true: 'color(rec2020 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200 200 200)' assert_true: 'color(rec2020 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200 200 200 / 200)' assert_true: 'color(rec2020 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 -200 -200 -200)' assert_true: 'color(rec2020 -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 -200 -200 -200 / -200)' assert_true: 'color(rec2020 -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200% 200% 200%)' assert_true: 'color(rec2020 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200% 200% 200% / 200%)' assert_true: 'color(rec2020 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 -200% -200% -200% / -200%)' assert_true: 'color(rec2020 -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 none none none / none)' assert_true: 'color(rec2020 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 none none none)' assert_true: 'color(rec2020 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 10% none none / none)' assert_true: 'color(rec2020 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 none none none / 0.5)' assert_true: 'color(rec2020 none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0 0 0 / none)' assert_true: 'color(rec2020 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0% 0% 0%)' assert_true: 'color(prophoto-rgb 0% 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 10% 10% 10%)' assert_true: 'color(prophoto-rgb 10% 10% 10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb .2 .2 25%)' assert_true: 'color(prophoto-rgb .2 .2 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0 0 0 / 1)' assert_true: 'color(prophoto-rgb 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0% 0 0 / 0.5)' assert_true: 'color(prophoto-rgb 0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 20% 0 10/0.5)' assert_true: 'color(prophoto-rgb 20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 20% 0 10/50%)' assert_true: 'color(prophoto-rgb 20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 400% 0 10/50%)' assert_true: 'color(prophoto-rgb 400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50% -160 160)' assert_true: 'color(prophoto-rgb 50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50% -200 200)' assert_true: 'color(prophoto-rgb 50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0 0 0 / -10%)' assert_true: 'color(prophoto-rgb 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0 0 0 / 110%)' assert_true: 'color(prophoto-rgb 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0 0 0 / 300%)' assert_true: 'color(prophoto-rgb 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50% -200)' assert_true: 'color(prophoto-rgb 50% -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50%)' assert_true: 'color(prophoto-rgb 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb)' assert_true: 'color(prophoto-rgb)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50% -200 / 0.5)' assert_true: 'color(prophoto-rgb 50% -200 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50% / 0.5)' assert_true: 'color(prophoto-rgb 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb / 0.5)' assert_true: 'color(prophoto-rgb / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200 200 200)' assert_true: 'color(prophoto-rgb 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200 200 200 / 200)' assert_true: 'color(prophoto-rgb 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb -200 -200 -200)' assert_true: 'color(prophoto-rgb -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb -200 -200 -200 / -200)' assert_true: 'color(prophoto-rgb -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200% 200% 200%)' assert_true: 'color(prophoto-rgb 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200% 200% 200% / 200%)' assert_true: 'color(prophoto-rgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb -200% -200% -200% / -200%)' assert_true: 'color(prophoto-rgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb none none none / none)' assert_true: 'color(prophoto-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb none none none)' assert_true: 'color(prophoto-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 10% none none / none)' assert_true: 'color(prophoto-rgb 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb none none none / 0.5)' assert_true: 'color(prophoto-rgb none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0 0 0 / none)' assert_true: 'color(prophoto-rgb 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0)' assert_true: 'color(xyz 0 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / 1)' assert_true: 'color(xyz 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1 1 1)' assert_true: 'color(xyz 1 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1 1 1 / 1)' assert_true: 'color(xyz 1 1 1 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz -1 -1 -1)' assert_true: 'color(xyz -1 -1 -1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0.1 0.1 0.1)' assert_true: 'color(xyz 0.1 0.1 0.1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 10 10 10)' assert_true: 'color(xyz 10 10 10)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz .2 .2 .25)' assert_true: 'color(xyz .2 .2 .25)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / 0.5)' assert_true: 'color(xyz 0 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz .20 0 10/0.5)' assert_true: 'color(xyz .20 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz .20 0 10/50%)' assert_true: 'color(xyz .20 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / -10%)' assert_true: 'color(xyz 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / 110%)' assert_true: 'color(xyz 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / 300%)' assert_true: 'color(xyz 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1 1)' assert_true: 'color(xyz 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1)' assert_true: 'color(xyz 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz)' assert_true: 'color(xyz)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1 1 / .5)' assert_true: 'color(xyz 1 1 / .5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1 / 0.5)' assert_true: 'color(xyz 1 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz / 50%)' assert_true: 'color(xyz / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz none none none / none)' assert_true: 'color(xyz none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz none none none)' assert_true: 'color(xyz none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0.2 none none / none)' assert_true: 'color(xyz 0.2 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz none none none / 0.5)' assert_true: 'color(xyz none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / none)' assert_true: 'color(xyz 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0)' assert_true: 'color(xyz-d50 0 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / 1)' assert_true: 'color(xyz-d50 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1 1 1)' assert_true: 'color(xyz-d50 1 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1 1 1 / 1)' assert_true: 'color(xyz-d50 1 1 1 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 -1 -1 -1)' assert_true: 'color(xyz-d50 -1 -1 -1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0.1 0.1 0.1)' assert_true: 'color(xyz-d50 0.1 0.1 0.1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 10 10 10)' assert_true: 'color(xyz-d50 10 10 10)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 .2 .2 .25)' assert_true: 'color(xyz-d50 .2 .2 .25)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / 0.5)' assert_true: 'color(xyz-d50 0 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 .20 0 10/0.5)' assert_true: 'color(xyz-d50 .20 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 .20 0 10/50%)' assert_true: 'color(xyz-d50 .20 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / -10%)' assert_true: 'color(xyz-d50 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / 110%)' assert_true: 'color(xyz-d50 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / 300%)' assert_true: 'color(xyz-d50 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1 1)' assert_true: 'color(xyz-d50 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1)' assert_true: 'color(xyz-d50 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50)' assert_true: 'color(xyz-d50)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1 1 / .5)' assert_true: 'color(xyz-d50 1 1 / .5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1 / 0.5)' assert_true: 'color(xyz-d50 1 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 / 50%)' assert_true: 'color(xyz-d50 / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 none none none / none)' assert_true: 'color(xyz-d50 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 none none none)' assert_true: 'color(xyz-d50 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0.2 none none / none)' assert_true: 'color(xyz-d50 0.2 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 none none none / 0.5)' assert_true: 'color(xyz-d50 none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / none)' assert_true: 'color(xyz-d50 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0)' assert_true: 'color(xyz-d65 0 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / 1)' assert_true: 'color(xyz-d65 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1 1 1)' assert_true: 'color(xyz-d65 1 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1 1 1 / 1)' assert_true: 'color(xyz-d65 1 1 1 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 -1 -1 -1)' assert_true: 'color(xyz-d65 -1 -1 -1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0.1 0.1 0.1)' assert_true: 'color(xyz-d65 0.1 0.1 0.1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 10 10 10)' assert_true: 'color(xyz-d65 10 10 10)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 .2 .2 .25)' assert_true: 'color(xyz-d65 .2 .2 .25)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / 0.5)' assert_true: 'color(xyz-d65 0 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 .20 0 10/0.5)' assert_true: 'color(xyz-d65 .20 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 .20 0 10/50%)' assert_true: 'color(xyz-d65 .20 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / -10%)' assert_true: 'color(xyz-d65 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / 110%)' assert_true: 'color(xyz-d65 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / 300%)' assert_true: 'color(xyz-d65 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1 1)' assert_true: 'color(xyz-d65 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1)' assert_true: 'color(xyz-d65 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65)' assert_true: 'color(xyz-d65)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1 1 / .5)' assert_true: 'color(xyz-d65 1 1 / .5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1 / 0.5)' assert_true: 'color(xyz-d65 1 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 / 50%)' assert_true: 'color(xyz-d65 / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 none none none / none)' assert_true: 'color(xyz-d65 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 none none none)' assert_true: 'color(xyz-d65 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0.2 none none / none)' assert_true: 'color(xyz-d65 0.2 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 none none none / 0.5)' assert_true: 'color(xyz-d65 none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / none)' assert_true: 'color(xyz-d65 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0)' assert_true: 'lab(0% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / 1)' assert_true: 'lab(0% 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / 0.5)' assert_true: 'lab(0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lab(20% 0 10/0.5)' assert_true: 'lab(20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lab(20% 0 10/50%)' assert_true: 'lab(20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'lab(400% 0 10/50%)' assert_true: 'lab(400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'lab(50% -160 160)' assert_true: 'lab(50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'lab(50% -200 200)' assert_true: 'lab(50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / -10%)' assert_true: 'lab(0% 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / 110%)' assert_true: 'lab(0% 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / 300%)' assert_true: 'lab(0% 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'lab(-40% 0 0)' assert_true: 'lab(-40% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'lab(50% -20 0)' assert_true: 'lab(50% -20 0)' is a supported value for color. expected true got false +FAIL Property color value 'lab(50% 0 -20)' assert_true: 'lab(50% 0 -20)' is a supported value for color. expected true got false +FAIL Property color value 'lab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' assert_true: 'lab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'lab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' assert_true: 'lab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'lab(none none none / none)' assert_true: 'lab(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(none none none)' assert_true: 'lab(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(20% none none / none)' assert_true: 'lab(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(none none none / 0.5)' assert_true: 'lab(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / none)' assert_true: 'lab(0% 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0)' assert_true: 'oklab(0% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / 1)' assert_true: 'oklab(0% 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / 0.5)' assert_true: 'oklab(0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(20% 0 10/0.5)' assert_true: 'oklab(20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(20% 0 10/50%)' assert_true: 'oklab(20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(400% 0 10/50%)' assert_true: 'oklab(400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(50% -160 160)' assert_true: 'oklab(50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(50% -200 200)' assert_true: 'oklab(50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / -10%)' assert_true: 'oklab(0% 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / 110%)' assert_true: 'oklab(0% 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / 300%)' assert_true: 'oklab(0% 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(-40% 0 0)' assert_true: 'oklab(-40% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(50% -20 0)' assert_true: 'oklab(50% -20 0)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(50% 0 -20)' assert_true: 'oklab(50% 0 -20)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' assert_true: 'oklab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'oklab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' assert_true: 'oklab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'oklab(none none none / none)' assert_true: 'oklab(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(none none none)' assert_true: 'oklab(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(20% none none / none)' assert_true: 'oklab(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(none none none / 0.5)' assert_true: 'oklab(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / none)' assert_true: 'oklab(0% 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(0% 0 0deg)' assert_true: 'lch(0% 0 0deg)' is a supported value for color. expected true got false +FAIL Property color value 'lch(0% 0 0deg / 1)' assert_true: 'lch(0% 0 0deg / 1)' is a supported value for color. expected true got false +FAIL Property color value 'lch(0% 0 0deg / 0.5)' assert_true: 'lch(0% 0 0deg / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lch(100% 230 0deg / 0.5)' assert_true: 'lch(100% 230 0deg / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lch(20% 50 20deg/0.5)' assert_true: 'lch(20% 50 20deg/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lch(20% 50 20deg/50%)' assert_true: 'lch(20% 50 20deg/50%)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 20deg / -10%)' assert_true: 'lch(10% 20 20deg / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 20deg / 110%)' assert_true: 'lch(10% 20 20deg / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 1.28rad)' assert_true: 'lch(10% 20 1.28rad)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 380deg)' assert_true: 'lch(10% 20 380deg)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 -340deg)' assert_true: 'lch(10% 20 -340deg)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 740deg)' assert_true: 'lch(10% 20 740deg)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 -700deg)' assert_true: 'lch(10% 20 -700deg)' is a supported value for color. expected true got false +FAIL Property color value 'lch(-40% 0 0)' assert_true: 'lch(-40% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'lch(20% -20 0)' assert_true: 'lch(20% -20 0)' is a supported value for color. expected true got false +FAIL Property color value 'lch(0% 0 0 / 0.5)' assert_true: 'lch(0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 20 / 110%)' assert_true: 'lch(10% 20 20 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 -700)' assert_true: 'lch(10% 20 -700)' is a supported value for color. expected true got false +FAIL Property color value 'lch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' assert_true: 'lch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'lch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' assert_true: 'lch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'lch(none none none / none)' assert_true: 'lch(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(none none none)' assert_true: 'lch(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(20% none none / none)' assert_true: 'lch(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(none none none / 0.5)' assert_true: 'lch(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lch(0% 0 0 / none)' assert_true: 'lch(0% 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(0% 0 0deg)' assert_true: 'oklch(0% 0 0deg)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(0% 0 0deg / 1)' assert_true: 'oklch(0% 0 0deg / 1)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(0% 0 0deg / 0.5)' assert_true: 'oklch(0% 0 0deg / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(100% 230 0deg / 0.5)' assert_true: 'oklch(100% 230 0deg / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(20% 50 20deg/0.5)' assert_true: 'oklch(20% 50 20deg/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(20% 50 20deg/50%)' assert_true: 'oklch(20% 50 20deg/50%)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 20deg / -10%)' assert_true: 'oklch(10% 20 20deg / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 20deg / 110%)' assert_true: 'oklch(10% 20 20deg / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 1.28rad)' assert_true: 'oklch(10% 20 1.28rad)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 380deg)' assert_true: 'oklch(10% 20 380deg)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 -340deg)' assert_true: 'oklch(10% 20 -340deg)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 740deg)' assert_true: 'oklch(10% 20 740deg)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 -700deg)' assert_true: 'oklch(10% 20 -700deg)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(-40% 0 0)' assert_true: 'oklch(-40% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(20% -20 0)' assert_true: 'oklch(20% -20 0)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(0% 0 0 / 0.5)' assert_true: 'oklch(0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 20 / 110%)' assert_true: 'oklch(10% 20 20 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 -700)' assert_true: 'oklch(10% 20 -700)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' assert_true: 'oklch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'oklch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' assert_true: 'oklch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'oklch(none none none / none)' assert_true: 'oklch(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(none none none)' assert_true: 'oklch(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(20% none none / none)' assert_true: 'oklch(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(none none none / 0.5)' assert_true: 'oklch(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(0% 0 0 / none)' assert_true: 'oklch(0% 0 0 / none)' is a supported value for color. expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-mix-computed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-mix-computed-expected.txt new file mode 100644 index 0000000..b9c96909 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-mix-computed-expected.txt
@@ -0,0 +1,478 @@ +This is a testharness.js-based test. +Found 474 tests; 0 PASS, 474 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(none none none), hsl(none none none))' assert_true: 'color-mix(in hsl, hsl(none none none), hsl(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))' assert_true: 'color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))' assert_true: 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))' assert_true: 'color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))' assert_true: 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))' assert_true: 'color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(none none none), hwb(none none none))' assert_true: 'color-mix(in hwb, hwb(none none none), hwb(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))' assert_true: 'color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, 25% lch(10% 20 30deg), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, 25% lch(10% 20 30deg), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), 25% lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg), 25% lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg) 25%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg) 75%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg) 30%, lch(50% 60 70deg) 90%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg) 30%, lch(50% 60 70deg) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg) 12.5%, lch(50% 60 70deg) 37.5%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg) 12.5%, lch(50% 60 70deg) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg) 0%, lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg) 0%, lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, 25% lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))' assert_true: 'color-mix(in lch, 25% lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4), 25% lch(50% 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4), 25% lch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) 25%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8) 75%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4) 30%, lch(50% 60 70deg / .8) 90%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4) 30%, lch(50% 60 70deg / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4) 12.5%, lch(50% 60 70deg / .8) 37.5%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4) 12.5%, lch(50% 60 70deg / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(none none none), lch(none none none))' assert_true: 'color-mix(in lch, lch(none none none), lch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(none none none), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(none none none), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(none none none))' assert_true: 'color-mix(in lch, lch(10% 20 30deg), lch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 none), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 none), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 none))' assert_true: 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(none 20 30deg), lch(50% none 70deg))' assert_true: 'color-mix(in lch, lch(none 20 30deg), lch(50% none 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / 0.5))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / none))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, 25% oklch(10% 20 30deg), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, 25% oklch(10% 20 30deg), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), 25% oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), 25% oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg) 25%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg) 75%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 30%, oklch(50% 60 70deg) 90%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg) 30%, oklch(50% 60 70deg) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 12.5%, oklch(50% 60 70deg) 37.5%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg) 12.5%, oklch(50% 60 70deg) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 0%, oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg) 0%, oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, 25% oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))' assert_true: 'color-mix(in oklch, 25% oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4), 25% oklch(50% 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4), 25% oklch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8) 25%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8) 75%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4) 30%, oklch(50% 60 70deg / .8) 90%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4) 30%, oklch(50% 60 70deg / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4) 12.5%, oklch(50% 60 70deg / .8) 37.5%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4) 12.5%, oklch(50% 60 70deg / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4) 0%, oklch(50% 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4) 0%, oklch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(none none none), oklch(none none none))' assert_true: 'color-mix(in oklch, oklch(none none none), oklch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(none none none), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(none none none), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(none none none))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), oklch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 none), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 none), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 none))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(none 20 30deg), oklch(50% none 70deg))' assert_true: 'color-mix(in oklch, oklch(none 20 30deg), oklch(50% none 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / 0.5))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / none))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, 25% lab(10% 20 30), lab(50% 60 70))' assert_true: 'color-mix(in lab, 25% lab(10% 20 30), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), 25% lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30), 25% lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), lab(50% 60 70) 25%)' assert_true: 'color-mix(in lab, lab(10% 20 30), lab(50% 60 70) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70) 75%)' assert_true: 'color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30) 30%, lab(50% 60 70) 90%)' assert_true: 'color-mix(in lab, lab(10% 20 30) 30%, lab(50% 60 70) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30) 12.5%, lab(50% 60 70) 37.5%)' assert_true: 'color-mix(in lab, lab(10% 20 30) 12.5%, lab(50% 60 70) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30) 0%, lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30) 0%, lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, 25% lab(10% 20 30 / .4), lab(50% 60 70 / .8))' assert_true: 'color-mix(in lab, 25% lab(10% 20 30 / .4), lab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4), 25% lab(50% 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4), 25% lab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) 25%)' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8) 75%)' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 30%, lab(50% 60 70 / .8) 90%)' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 30%, lab(50% 60 70 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(none none none), lab(none none none))' assert_true: 'color-mix(in lab, lab(none none none), lab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(none none none), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(none none none), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), lab(none none none))' assert_true: 'color-mix(in lab, lab(10% 20 30), lab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 none), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 none), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), lab(50% 60 none))' assert_true: 'color-mix(in lab, lab(10% 20 30), lab(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(none 20 30), lab(50% none 70))' assert_true: 'color-mix(in lab, lab(none 20 30), lab(50% none 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / 0.5))' assert_true: 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / none))' assert_true: 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, 25% oklab(10% 20 30), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, 25% oklab(10% 20 30), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), 25% oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30), 25% oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70) 25%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70) 75%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30) 30%, oklab(50% 60 70) 90%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30) 30%, oklab(50% 60 70) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30) 12.5%, oklab(50% 60 70) 37.5%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30) 12.5%, oklab(50% 60 70) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30) 0%, oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30) 0%, oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, 25% oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))' assert_true: 'color-mix(in oklab, 25% oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4), 25% oklab(50% 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4), 25% oklab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8) 25%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8) 75%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 30%, oklab(50% 60 70 / .8) 90%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 30%, oklab(50% 60 70 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 12.5%, oklab(50% 60 70 / .8) 37.5%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 12.5%, oklab(50% 60 70 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 0%, oklab(50% 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 0%, oklab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(none none none), oklab(none none none))' assert_true: 'color-mix(in oklab, oklab(none none none), oklab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(none none none), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(none none none), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(none none none))' assert_true: 'color-mix(in oklab, oklab(10% 20 30), oklab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 none), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 none), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 none))' assert_true: 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(none 20 30), oklab(50% none 70))' assert_true: 'color-mix(in oklab, oklab(none 20 30), oklab(50% none 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / 0.5))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / none))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7) 25%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), 25% color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), 25% color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7) 75%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 30%, color(srgb .5 .6 .7) 90%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 30%, color(srgb .5 .6 .7) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 12.5%, color(srgb .5 .6 .7) 37.5%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 12.5%, color(srgb .5 .6 .7) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 0%, color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 0%, color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .5), color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .5), color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, 25% color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, 25% color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), 25% color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), 25% color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))' assert_true: 'color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))' assert_true: 'color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))' assert_true: 'color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb none none none))' assert_true: 'color-mix(in srgb, color(srgb none none none), color(srgb none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))' assert_true: 'color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7) 25%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), 25% color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), 25% color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7) 75%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 30%, color(srgb-linear .5 .6 .7) 90%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 30%, color(srgb-linear .5 .6 .7) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 12.5%, color(srgb-linear .5 .6 .7) 37.5%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 12.5%, color(srgb-linear .5 .6 .7) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 0%, color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 0%, color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .5), color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .5), color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), 25% color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), 25% color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, 25% color(xyz .1 .2 .3), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, 25% color(xyz .1 .2 .3), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7) 25%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), 25% color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), 25% color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7) 75%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 30%, color(xyz .5 .6 .7) 90%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 30%, color(xyz .5 .6 .7) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 12.5%, color(xyz .5 .6 .7) 37.5%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 12.5%, color(xyz .5 .6 .7) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 0%, color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 0%, color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .5), color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .5), color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, 25% color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, 25% color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), 25% color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), 25% color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))' assert_true: 'color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))' assert_true: 'color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz none none none))' assert_true: 'color-mix(in xyz, color(xyz none none none), color(xyz none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))' assert_true: 'color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7) 25%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), 25% color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), 25% color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7) 75%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 30%, color(xyz-d50 .5 .6 .7) 90%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 30%, color(xyz-d50 .5 .6 .7) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 12.5%, color(xyz-d50 .5 .6 .7) 37.5%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 12.5%, color(xyz-d50 .5 .6 .7) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 0%, color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 0%, color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .5), color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .5), color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), 25% color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), 25% color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7) 25%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), 25% color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), 25% color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7) 75%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 30%, color(xyz-d65 .5 .6 .7) 90%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 30%, color(xyz-d65 .5 .6 .7) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 12.5%, color(xyz-d65 .5 .6 .7) 37.5%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 12.5%, color(xyz-d65 .5 .6 .7) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 0%, color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 0%, color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .5), color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .5), color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), 25% color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), 25% color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))' is a supported value for color. expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-mix-valid-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-mix-valid-expected.txt new file mode 100644 index 0000000..3d1143a --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-mix-valid-expected.txt
@@ -0,0 +1,478 @@ +This is a testharness.js-based test. +Found 474 tests; 0 PASS, 474 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(none none none), hsl(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(none none none), hwb(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, 25% lch(10% 20 30deg), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), 25% lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 30%, lch(50% 60 70deg) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 12.5%, lch(50% 60 70deg) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 0%, lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, 25% lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4), 25% lch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4) 30%, lch(50% 60 70deg / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4) 12.5%, lch(50% 60 70deg / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(none none none), lch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(none none none), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 none), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(none 20 30deg), lch(50% none 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, 25% oklch(10% 20 30deg), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), 25% oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 30%, oklch(50% 60 70deg) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 12.5%, oklch(50% 60 70deg) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 0%, oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, 25% oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4), 25% oklch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4) 30%, oklch(50% 60 70deg / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4) 12.5%, oklch(50% 60 70deg / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4) 0%, oklch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(none none none), oklch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(none none none), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 none), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(none 20 30deg), oklch(50% none 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, 25% lab(10% 20 30), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), 25% lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(50% 60 70) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30) 30%, lab(50% 60 70) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30) 12.5%, lab(50% 60 70) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30) 0%, lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, 25% lab(10% 20 30 / .4), lab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4), 25% lab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 30%, lab(50% 60 70 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(none none none), lab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(none none none), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 none), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(none 20 30), lab(50% none 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, 25% oklab(10% 20 30), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), 25% oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 30%, oklab(50% 60 70) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 12.5%, oklab(50% 60 70) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 0%, oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, 25% oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4), 25% oklab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 30%, oklab(50% 60 70 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 12.5%, oklab(50% 60 70 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 0%, oklab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(none none none), oklab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(none none none), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 none), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(none 20 30), oklab(50% none 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), 25% color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 30%, color(srgb .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 12.5%, color(srgb .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 0%, color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .5), color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, 25% color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4), 25% color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb none none none), color(srgb none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), 25% color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 30%, color(srgb-linear .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 12.5%, color(srgb-linear .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 0%, color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .5), color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), 25% color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, 25% color(xyz .1 .2 .3), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), 25% color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 30%, color(xyz .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 12.5%, color(xyz .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 0%, color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .5), color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, 25% color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4), 25% color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz none none none), color(xyz none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), 25% color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 30%, color(xyz-d50 .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 12.5%, color(xyz-d50 .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 0%, color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .5), color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), 25% color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), 25% color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 30%, color(xyz-d65 .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 12.5%, color(xyz-d65 .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 0%, color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .5), color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), 25% color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-valid-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-valid-expected.txt new file mode 100644 index 0000000..f1e4105 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/color-valid-expected.txt
@@ -0,0 +1,407 @@ +This is a testharness.js-based test. +Found 403 tests; 27 PASS, 376 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS e.style['color'] = "currentcolor" should set the property value +PASS e.style['color'] = "transparent" should set the property value +PASS e.style['color'] = "red" should set the property value +PASS e.style['color'] = "magenta" should set the property value +PASS e.style['color'] = "#234" should set the property value +PASS e.style['color'] = "#FEDCBA" should set the property value +PASS e.style['color'] = "rgb(2, 3, 4)" should set the property value +PASS e.style['color'] = "rgb(100%, 0%, 0%)" should set the property value +PASS e.style['color'] = "rgba(2, 3, 4, 0.5)" should set the property value +PASS e.style['color'] = "rgba(2, 3, 4, 50%)" should set the property value +PASS e.style['color'] = "hsl(120, 100%, 50%)" should set the property value +PASS e.style['color'] = "hsla(120, 100%, 50%, 0.25)" should set the property value +PASS e.style['color'] = "rgb(-2, 3, 4)" should set the property value +PASS e.style['color'] = "rgb(100, 200, 300)" should set the property value +PASS e.style['color'] = "rgb(20, 10, 0, -10)" should set the property value +PASS e.style['color'] = "rgb(100%, 200%, 300%)" should set the property value +FAIL e.style['color'] = "rgb(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(128 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(128 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(none none none / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(20% none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(none none none / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(128 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(128 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(20% none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 30% 50%)" should set the property value +PASS e.style['color'] = "hsl(120 30% 50% / 0.5)" should set the property value +FAIL e.style['color'] = "hsl(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(0 0% 0%)" should set the property value +FAIL e.style['color'] = "hsl(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(0 0% 0% / 0)" should set the property value +FAIL e.style['color'] = "hsla(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsla(0 0% 0%)" should set the property value +FAIL e.style['color'] = "hsla(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsla(0 0% 0% / 0)" should set the property value +FAIL e.style['color'] = "hsl(120 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 0% 0%)" should set the property value +FAIL e.style['color'] = "hsl(120 80% none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 80% 0%)" should set the property value +FAIL e.style['color'] = "hsl(120 none 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 0% 50%)" should set the property value +FAIL e.style['color'] = "hsl(120 100% 50% / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 100% 50% / 0)" should set the property value +FAIL e.style['color'] = "hsl(none 100% 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(0 100% 50%)" should set the property value +FAIL e.style['color'] = "hwb(120 30% 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 30% 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(0 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(0 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 80% none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 80% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 none 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 0% 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 30% 50% / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 30% 50% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(none 100% 50% / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(0 100% 50% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1 1 1 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz -1 -1 -1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0.1 0.1 0.1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 10 10 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz .2 .2 .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz .20 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz .20 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1 1 1 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 -1 -1 -1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0.1 0.1 0.1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 10 10 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 .2 .2 .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 .20 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 .20 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1 1 1 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 -1 -1 -1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0.1 0.1 0.1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 10 10 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 .2 .2 .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 .20 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 .20 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(-40% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(50% -20 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(50% 0 -20)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(-40% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(50% -20 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(50% 0 -20)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(0% 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(0% 0 0deg / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(0% 0 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(100% 230 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(20% 50 20deg/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(20% 50 20deg/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 20deg / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 20deg / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 1.28rad)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 380deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 -340deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 740deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 -700deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(-40% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(20% -20 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 20 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 -700)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(0% 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(0% 0 0deg / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(0% 0 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(100% 230 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(20% 50 20deg/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(20% 50 20deg/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 20deg / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 20deg / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 1.28rad)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 380deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 -340deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 740deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 -700deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(-40% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(20% -20 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 20 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 -700)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt similarity index 66% rename from third_party/blink/web_tests/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt rename to third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt index 6b9f5f9..a22d69e 100644 --- a/third_party/blink/web_tests/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt
@@ -1,11 +1,19 @@ This is a testharness.js-based test. -Found 586 tests; 0 PASS, 586 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 881 tests; 0 PASS, 881 FAIL, 0 TIMEOUT, 0 NOTRUN. FAIL Property color value 'rgb(from rebeccapurple r g b)' assert_true: 'rgb(from rebeccapurple r g b)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple r g b / alpha)' assert_true: 'rgb(from rebeccapurple r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)' assert_true: 'rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)' assert_true: 'rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rgb(from rebeccapurple r g b) r g b)' assert_true: 'rgb(from rgb(from rebeccapurple r g b) r g b)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from color(display-p3 0 1 0) r g b / alpha)' assert_true: 'rgb(from color(display-p3 0 1 0) r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lab(100% 104.3 -50.9) r g b)' assert_true: 'rgb(from lab(100% 104.3 -50.9) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lab(0% 104.3 -50.9) r g b)' assert_true: 'rgb(from lab(0% 104.3 -50.9) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lch(100% 116 334) r g b)' assert_true: 'rgb(from lch(100% 116 334) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lch(0% 116 334) r g b)' assert_true: 'rgb(from lch(0% 116 334) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklab(100% 0.365 -0.16) r g b)' assert_true: 'rgb(from oklab(100% 0.365 -0.16) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklab(0% 0.365 -0.16) r g b)' assert_true: 'rgb(from oklab(0% 0.365 -0.16) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklch(100% 0.399 336.3) r g b)' assert_true: 'rgb(from oklch(100% 0.399 336.3) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklch(0% 0.399 336.3) r g b)' assert_true: 'rgb(from oklch(0% 0.399 336.3) r g b)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple 0 0 0)' assert_true: 'rgb(from rebeccapurple 0 0 0)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple 0 0 0 / 0)' assert_true: 'rgb(from rebeccapurple 0 0 0 / 0)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple 0 g b / alpha)' assert_true: 'rgb(from rebeccapurple 0 g b / alpha)' is a supported value for color. expected true got false @@ -58,12 +66,31 @@ FAIL Property color value 'rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)' assert_true: 'rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)' assert_true: 'rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple none none none)' assert_true: 'rgb(from rebeccapurple none none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple none none none / none)' assert_true: 'rgb(from rebeccapurple none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple r g none)' assert_true: 'rgb(from rebeccapurple r g none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple r g none / alpha)' assert_true: 'rgb(from rebeccapurple r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple r g b / none)' assert_true: 'rgb(from rebeccapurple r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)' assert_true: 'rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% 40% 60% / 80%) r g b / none)' assert_true: 'rgb(from rgb(20% 40% 60% / 80%) r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(none none none) r g b)' assert_true: 'rgb(from rgb(none none none) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(none none none / none) r g b / alpha)' assert_true: 'rgb(from rgb(none none none / none) r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% none 60%) r g b)' assert_true: 'rgb(from rgb(20% none 60%) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% 40% 60% / none) r g b / alpha)' assert_true: 'rgb(from rgb(20% 40% 60% / none) r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple h s l)' assert_true: 'hsl(from rebeccapurple h s l)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple h s l / alpha)' assert_true: 'hsl(from rebeccapurple h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)' assert_true: 'hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from hsl(from rebeccapurple h s l) h s l)' assert_true: 'hsl(from hsl(from rebeccapurple h s l) h s l)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from color(display-p3 0 1 0) h s l / alpha)' assert_true: 'hsl(from color(display-p3 0 1 0) h s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lab(100% 104.3 -50.9) h s l)' assert_true: 'hsl(from lab(100% 104.3 -50.9) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lab(0% 104.3 -50.9) h s l)' assert_true: 'hsl(from lab(0% 104.3 -50.9) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lch(100% 116 334) h s l)' assert_true: 'hsl(from lch(100% 116 334) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lch(0% 116 334) h s l)' assert_true: 'hsl(from lch(0% 116 334) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklab(100% 0.365 -0.16) h s l)' assert_true: 'hsl(from oklab(100% 0.365 -0.16) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklab(0% 0.365 -0.16) h s l)' assert_true: 'hsl(from oklab(0% 0.365 -0.16) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklch(100% 0.399 336.3) h s l)' assert_true: 'hsl(from oklch(100% 0.399 336.3) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklch(0% 0.399 336.3) h s l)' assert_true: 'hsl(from oklch(0% 0.399 336.3) h s l)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple 0 0% 0%)' assert_true: 'hsl(from rebeccapurple 0 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple 0deg 0% 0%)' assert_true: 'hsl(from rebeccapurple 0deg 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple 0 0% 0% / 0)' assert_true: 'hsl(from rebeccapurple 0 0% 0% / 0)' is a supported value for color. expected true got false @@ -98,12 +125,34 @@ FAIL Property color value 'hsl(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' assert_true: 'hsl(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple calc(h) calc(s) calc(l))' assert_true: 'hsl(from rebeccapurple calc(h) calc(s) calc(l))' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))' assert_true: 'hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple none none none)' assert_true: 'hsl(from rebeccapurple none none none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple none none none / none)' assert_true: 'hsl(from rebeccapurple none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple h s none)' assert_true: 'hsl(from rebeccapurple h s none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple h s none / alpha)' assert_true: 'hsl(from rebeccapurple h s none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple h s l / none)' assert_true: 'hsl(from rebeccapurple h s l / none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple none s l / alpha)' assert_true: 'hsl(from rebeccapurple none s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) h s l / none)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) h s l / none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(none none none) h s l)' assert_true: 'hsl(from hsl(none none none) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(none none none / none) h s l / alpha)' assert_true: 'hsl(from hsl(none none none / none) h s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg none 50% / .5) h s l)' assert_true: 'hsl(from hsl(120deg none 50% / .5) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / none) h s l / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / none) h s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(none 20% 50% / .5) h s l / alpha)' assert_true: 'hsl(from hsl(none 20% 50% / .5) h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple h w b)' assert_true: 'hwb(from rebeccapurple h w b)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple h w b / alpha)' assert_true: 'hwb(from rebeccapurple h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)' assert_true: 'hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)' assert_true: 'hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from hwb(from rebeccapurple h w b) h w b)' assert_true: 'hwb(from hwb(from rebeccapurple h w b) h w b)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from color(display-p3 0 1 0) h w b / alpha)' assert_true: 'hwb(from color(display-p3 0 1 0) h w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lab(100% 104.3 -50.9) h w b)' assert_true: 'hwb(from lab(100% 104.3 -50.9) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lab(0% 104.3 -50.9) h w b)' assert_true: 'hwb(from lab(0% 104.3 -50.9) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lch(100% 116 334) h w b)' assert_true: 'hwb(from lch(100% 116 334) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lch(0% 116 334) h w b)' assert_true: 'hwb(from lch(0% 116 334) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklab(100% 0.365 -0.16) h w b)' assert_true: 'hwb(from oklab(100% 0.365 -0.16) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklab(0% 0.365 -0.16) h w b)' assert_true: 'hwb(from oklab(0% 0.365 -0.16) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklch(100% 0.399 336.3) h w b)' assert_true: 'hwb(from oklch(100% 0.399 336.3) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklch(0% 0.399 336.3) h w b)' assert_true: 'hwb(from oklch(0% 0.399 336.3) h w b)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple 0 0% 0%)' assert_true: 'hwb(from rebeccapurple 0 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple 0deg 0% 0%)' assert_true: 'hwb(from rebeccapurple 0deg 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple 0 0% 0% / 0)' assert_true: 'hwb(from rebeccapurple 0 0% 0% / 0)' is a supported value for color. expected true got false @@ -138,9 +187,25 @@ FAIL Property color value 'hwb(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' assert_true: 'hwb(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple calc(h) calc(w) calc(b))' assert_true: 'hwb(from rebeccapurple calc(h) calc(w) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))' assert_true: 'hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple none none none)' assert_true: 'hwb(from rebeccapurple none none none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple none none none / none)' assert_true: 'hwb(from rebeccapurple none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple h w none)' assert_true: 'hwb(from rebeccapurple h w none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple h w none / alpha)' assert_true: 'hwb(from rebeccapurple h w none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple h w b / none)' assert_true: 'hwb(from rebeccapurple h w b / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple none w b / alpha)' assert_true: 'hwb(from rebeccapurple none w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)' assert_true: 'hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / .5) h w b / none)' assert_true: 'hwb(from hwb(120deg 20% 50% / .5) h w b / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)' assert_true: 'hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(none none none) h w b)' assert_true: 'hwb(from hwb(none none none) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(none none none / none) h w b / alpha)' assert_true: 'hwb(from hwb(none none none / none) h w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg none 50% / .5) h w b)' assert_true: 'hwb(from hwb(120deg none 50% / .5) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / none) h w b / alpha)' assert_true: 'hwb(from hwb(120deg 20% 50% / none) h w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(none 20% 50% / .5) h w b / alpha)' assert_true: 'hwb(from hwb(none 20% 50% / .5) h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l a b)' assert_true: 'lab(from lab(25% 20 50) l a b)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l a b / alpha)' assert_true: 'lab(from lab(25% 20 50) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a b / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(200% 300 400 / 500%) l a b / alpha)' assert_true: 'lab(from lab(200% 300 400 / 500%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(-200% -300 -400 / -500%) l a b / alpha)' assert_true: 'lab(from lab(-200% -300 -400 / -500%) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(from lab(25% 20 50) l a b) l a b)' assert_true: 'lab(from lab(from lab(25% 20 50) l a b) l a b)' is a supported value for color. expected true got false FAIL Property color value 'lab(from color(display-p3 0 0 0) l a b / alpha)' assert_true: 'lab(from color(display-p3 0 0 0) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) 0% 0 0)' assert_true: 'lab(from lab(25% 20 50) 0% 0 0)' is a supported value for color. expected true got false @@ -161,15 +226,30 @@ FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l 35 b / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l 35 b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a 35 / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a 35 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a b / .35)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a b / .35)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'lab(from lab(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'lab(from lab(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l b a)' assert_true: 'lab(from lab(25% 20 50) l b a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l a a / a)' assert_true: 'lab(from lab(25% 20 50) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l b a)' assert_true: 'lab(from lab(25% 20 50 / 40%) l b a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a a / a)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) calc(l) calc(a) calc(b))' assert_true: 'lab(from lab(25% 20 50) calc(l) calc(a) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' assert_true: 'lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) none none none)' assert_true: 'lab(from lab(25% 20 50) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) none none none / none)' assert_true: 'lab(from lab(25% 20 50) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) l a none)' assert_true: 'lab(from lab(25% 20 50) l a none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) l a none / alpha)' assert_true: 'lab(from lab(25% 20 50) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) l a b / none)' assert_true: 'lab(from lab(25% 20 50) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a none / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a b / none)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(none none none) l a b)' assert_true: 'lab(from lab(none none none) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(none none none / none) l a b / alpha)' assert_true: 'lab(from lab(none none none / none) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% none 50) l a b)' assert_true: 'lab(from lab(25% none 50) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50 / none) l a b / alpha)' assert_true: 'lab(from lab(25% 20 50 / none) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l a b)' assert_true: 'oklab(from oklab(25% 20 50) l a b)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l a b / alpha)' assert_true: 'oklab(from oklab(25% 20 50) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a b / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(200% 300 400 / 500%) l a b / alpha)' assert_true: 'oklab(from oklab(200% 300 400 / 500%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(-200% -300 -400 / -500%) l a b / alpha)' assert_true: 'oklab(from oklab(-200% -300 -400 / -500%) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(from oklab(25% 20 50) l a b) l a b)' assert_true: 'oklab(from oklab(from oklab(25% 20 50) l a b) l a b)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from color(display-p3 0 0 0) l a b / alpha)' assert_true: 'oklab(from color(display-p3 0 0 0) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) 0% 0 0)' assert_true: 'oklab(from oklab(25% 20 50) 0% 0 0)' is a supported value for color. expected true got false @@ -190,15 +270,30 @@ FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l 35 b / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l 35 b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a 35 / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a 35 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a b / .35)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a b / .35)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'oklab(from oklab(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'oklab(from oklab(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l b a)' assert_true: 'oklab(from oklab(25% 20 50) l b a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l a a / a)' assert_true: 'oklab(from oklab(25% 20 50) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l b a)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l b a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a a / a)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) calc(l) calc(a) calc(b))' assert_true: 'oklab(from oklab(25% 20 50) calc(l) calc(a) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' assert_true: 'oklab(from oklab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) none none none)' assert_true: 'oklab(from oklab(25% 20 50) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) none none none / none)' assert_true: 'oklab(from oklab(25% 20 50) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) l a none)' assert_true: 'oklab(from oklab(25% 20 50) l a none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) l a none / alpha)' assert_true: 'oklab(from oklab(25% 20 50) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) l a b / none)' assert_true: 'oklab(from oklab(25% 20 50) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a none / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a b / none)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(none none none) l a b)' assert_true: 'oklab(from oklab(none none none) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(none none none / none) l a b / alpha)' assert_true: 'oklab(from oklab(none none none / none) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% none 50) l a b)' assert_true: 'oklab(from oklab(25% none 50) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50 / none) l a b / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / none) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) l c h)' assert_true: 'lch(from lch(70% 45 30) l c h)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) l c h / alpha)' assert_true: 'lch(from lch(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false -FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h/ alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h/ alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(200% 300 400 / 500%) l c h / alpha)' assert_true: 'lch(from lch(200% 300 400 / 500%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(-200% -300 -400 / -500%) l c h / alpha)' assert_true: 'lch(from lch(-200% -300 -400 / -500%) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(from lch(70% 45 30) l c h) l c h)' assert_true: 'lch(from lch(from lch(70% 45 30) l c h) l c h)' is a supported value for color. expected true got false FAIL Property color value 'lch(from color(display-p3 0 0 0) l c h / alpha)' assert_true: 'lch(from color(display-p3 0 0 0) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lab(70% 45 30) l c h / alpha)' assert_true: 'lch(from lab(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false @@ -226,6 +321,10 @@ FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c 25 / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c 25 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h / .25)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h / .25)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'lch(from lch(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'lch(from lch(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) 50% 120 400deg / 500)' assert_true: 'lch(from lch(70% 45 30 / 40%) 50% 120 400deg / 500)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) 50% 120 -400deg / -500)' assert_true: 'lch(from lch(70% 45 30 / 40%) 50% 120 -400deg / -500)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) alpha c h / l)' assert_true: 'lch(from lch(70% 45 30) alpha c h / l)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) l c c / alpha)' assert_true: 'lch(from lch(70% 45 30) l c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) alpha c h / alpha)' assert_true: 'lch(from lch(70% 45 30) alpha c h / alpha)' is a supported value for color. expected true got false @@ -236,9 +335,22 @@ FAIL Property color value 'lch(from lch(70% 45 30 / 40%) alpha c c / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) alpha c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) calc(l) calc(c) calc(h))' assert_true: 'lch(from lch(70% 45 30) calc(l) calc(c) calc(h))' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' assert_true: 'lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) none none none)' assert_true: 'lch(from lch(70% 45 30) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) none none none / none)' assert_true: 'lch(from lch(70% 45 30) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) l c none)' assert_true: 'lch(from lch(70% 45 30) l c none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) l c none / alpha)' assert_true: 'lch(from lch(70% 45 30) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) l c h / none)' assert_true: 'lch(from lch(70% 45 30) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c none / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h / none)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(none none none) l c h)' assert_true: 'lch(from lch(none none none) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(none none none / none) l c h / alpha)' assert_true: 'lch(from lch(none none none / none) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% none 30) l c h)' assert_true: 'lch(from lch(70% none 30) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / none) l c h / alpha)' assert_true: 'lch(from lch(70% 45 30 / none) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) l c h)' assert_true: 'oklch(from oklch(70% 45 30) l c h)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) l c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false -FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h/ alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h/ alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(200% 300 400 / 500%) l c h / alpha)' assert_true: 'oklch(from oklch(200% 300 400 / 500%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(-200% -300 -400 / -500%) l c h / alpha)' assert_true: 'oklch(from oklch(-200% -300 -400 / -500%) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(from oklch(70% 45 30) l c h) l c h)' assert_true: 'oklch(from oklch(from oklch(70% 45 30) l c h) l c h)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from color(display-p3 0 0 0) l c h / alpha)' assert_true: 'oklch(from color(display-p3 0 0 0) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklab(70% 45 30) l c h / alpha)' assert_true: 'oklch(from oklab(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false @@ -266,6 +378,10 @@ FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c 25 / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c 25 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c 25deg / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c 25deg / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h / .25)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h / .25)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) 50% 120 400deg / 500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) 50% 120 400deg / 500)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) 50% 120 -400deg / -500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) 50% 120 -400deg / -500)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) alpha c h / l)' assert_true: 'oklch(from oklch(70% 45 30) alpha c h / l)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) l c c / alpha)' assert_true: 'oklch(from oklch(70% 45 30) l c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) alpha c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30) alpha c h / alpha)' is a supported value for color. expected true got false @@ -276,6 +392,17 @@ FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) alpha c c / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) alpha c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) calc(l) calc(c) calc(h))' assert_true: 'oklch(from oklch(70% 45 30) calc(l) calc(c) calc(h))' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' assert_true: 'oklch(from oklch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) none none none)' assert_true: 'oklch(from oklch(70% 45 30) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) none none none / none)' assert_true: 'oklch(from oklch(70% 45 30) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) l c none)' assert_true: 'oklch(from oklch(70% 45 30) l c none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) l c none / alpha)' assert_true: 'oklch(from oklch(70% 45 30) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) l c h / none)' assert_true: 'oklch(from oklch(70% 45 30) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c none / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h / none)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(none none none) l c h)' assert_true: 'oklch(from oklch(none none none) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(none none none / none) l c h / alpha)' assert_true: 'oklch(from oklch(none none none / none) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% none 30) l c h)' assert_true: 'oklch(from oklch(70% none 30) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / none) l c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / none) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g b)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b)' is a supported value for color. expected true got false @@ -307,6 +434,14 @@ FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 20% / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0.2)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 20%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4 / 5)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4 / -5)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400% / 500%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400% / -500%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb g b r)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb b alpha r / g)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r r r / r)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r r r / r)' is a supported value for color. expected true got false @@ -315,8 +450,27 @@ FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb b alpha r / g)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r r r / r)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb alpha alpha alpha / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3) srgb r g b)' assert_true: 'color(from color(srgb 1.7 1.5 1.3) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3) srgb r g b / alpha)' assert_true: 'color(from color(srgb 1.7 1.5 1.3) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b)' assert_true: 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b / alpha)' assert_true: 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b / alpha)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b / alpha)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb calc(r) calc(g) calc(b))' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb none none none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb none none none / none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g none / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g none / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb none none none) srgb r g b)' assert_true: 'color(from color(srgb none none none) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb none none none / none) srgb r g b / alpha)' assert_true: 'color(from color(srgb none none none / none) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 none 0.3) srgb r g b)' assert_true: 'color(from color(srgb 0.7 none 0.3) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / none) srgb r g b / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / none) srgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b)' is a supported value for color. expected true got false @@ -348,6 +502,14 @@ FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 20% / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0.2)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 20%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4 / 5)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4 / -5)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400% / 500%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400% / -500%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear g b r)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear b alpha r / g)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r r r / r)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r r r / r)' is a supported value for color. expected true got false @@ -356,8 +518,27 @@ FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear b alpha r / g)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r r r / r)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear alpha alpha alpha / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear calc(r) calc(g) calc(b))' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none / none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g none / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear none none none) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear none none none) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear none none none / none) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear none none none / none) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 none 0.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 0.7 none 0.3) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / none) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / none) srgb-linear r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b)' is a supported value for color. expected true got false @@ -389,6 +570,14 @@ FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 20% / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0.2)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 20%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4 / 5)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4 / -5)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400% / 500%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400% / -500%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb g b r)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb b alpha r / g)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r r r / r)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r r r / r)' is a supported value for color. expected true got false @@ -397,8 +586,27 @@ FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb b alpha r / g)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r r r / r)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb alpha alpha alpha / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb calc(r) calc(g) calc(b))' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none / none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g none / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb none none none) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb none none none) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb none none none / none) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb none none none / none) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 none 0.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 0.7 none 0.3) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / none) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / none) a98-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b)' is a supported value for color. expected true got false @@ -430,6 +638,14 @@ FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 20% / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0.2)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 20%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4 / 5)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4 / -5)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400% / 500%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400% / -500%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 g b r)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 b alpha r / g)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r r r / r)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r r r / r)' is a supported value for color. expected true got false @@ -438,8 +654,27 @@ FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 b alpha r / g)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r r r / r)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 alpha alpha alpha / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 calc(r) calc(g) calc(b))' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none / none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g none / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 none none none) rec2020 r g b)' assert_true: 'color(from color(rec2020 none none none) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 none none none / none) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 none none none / none) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 none 0.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 0.7 none 0.3) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / none) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / none) rec2020 r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b)' is a supported value for color. expected true got false @@ -471,6 +706,14 @@ FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 20% / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0.2)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 20%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4 / 5)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4 / -5)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400% / 500%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400% / -500%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb g b r)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb b alpha r / g)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r r r / r)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r r r / r)' is a supported value for color. expected true got false @@ -479,8 +722,27 @@ FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb b alpha r / g)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r r r / r)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb alpha alpha alpha / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb calc(r) calc(g) calc(b))' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none / none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g none / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb none none none) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb none none none) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb none none none / none) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb none none none / none) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 none 0.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 0.7 none 0.3) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / none) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / none) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y z)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y z)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y z / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z)' is a supported value for color. expected true got false @@ -511,6 +773,17 @@ FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x x x / x)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x x x / x)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz calc(x) calc(y) calc(z))' assert_true: 'color(from color(xyz 7 -20.5 100) xyz calc(x) calc(y) calc(z))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz calc(x) calc(y) calc(z) / calc(alpha))' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz calc(x) calc(y) calc(z) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz none none none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz none none none / none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y none / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y z / none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y none / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / none)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz none none none) xyz x y z)' assert_true: 'color(from color(xyz none none none) xyz x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz none none none / none) xyz x y z / alpha)' assert_true: 'color(from color(xyz none none none / none) xyz x y z / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 none 100) xyz x y z)' assert_true: 'color(from color(xyz 7 none 100) xyz x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100 / none) xyz x y z / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100 / none) xyz x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z)' is a supported value for color. expected true got false @@ -541,6 +814,17 @@ FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x x x / x)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x x x / x)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 calc(x) calc(y) calc(z))' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 calc(x) calc(y) calc(z))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 calc(x) calc(y) calc(z) / calc(alpha))' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 calc(x) calc(y) calc(z) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none / none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y none / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 none none none) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 none none none) xyz-d50 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 none none none / none) xyz-d50 x y z / alpha)' assert_true: 'color(from color(xyz-d50 none none none / none) xyz-d50 x y z / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 none 100) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 7 none 100) xyz-d50 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / none) xyz-d50 x y z / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / none) xyz-d50 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z)' is a supported value for color. expected true got false @@ -571,6 +855,17 @@ FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x x x / x)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x x x / x)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 calc(x) calc(y) calc(z))' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 calc(x) calc(y) calc(z))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 calc(x) calc(y) calc(z) / calc(alpha))' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 calc(x) calc(y) calc(z) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none / none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y none / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 none none none) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 none none none) xyz-d65 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)' assert_true: 'color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 none 100) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 7 none 100) xyz-d65 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from var(--bg-color) r g b / 80%)' assert_equals: expected "rgba(0, 0, 255, 0.8)" but got "rgb(0, 0, 0)" FAIL Property color value 'lch(from var(--color) calc(l / 2) c h)' assert_equals: expected "lch(23.138971% 67.989716 134.39125)" but got "rgb(0, 0, 0)" FAIL Property color value 'rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))' assert_equals: expected "rgb(76, 76, 76)" but got "rgb(0, 0, 0)"
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/relative-color-valid-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/relative-color-valid-expected.txt new file mode 100644 index 0000000..612ee9b --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/external/wpt/css/css-color/parsing/relative-color-valid-expected.txt
@@ -0,0 +1,885 @@ +This is a testharness.js-based test. +Found 881 tests; 13 PASS, 868 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL e.style['color'] = "rgb(from rebeccapurple r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(from rebeccapurple r g b) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from color(display-p3 0 1 0) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lab(100% 104.3 -50.9) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lab(0% 104.3 -50.9) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lch(100% 116 334) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lch(0% 116 334) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklab(100% 0.365 -0.16) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklab(0% 0.365 -0.16) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklch(100% 0.399 336.3) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklch(0% 0.399 336.3) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 25 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 25 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g b / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / .20)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 25 g b / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 25 b / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g 25 / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 20% 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 10 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 0% 10 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 20% 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 10 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 0% 10 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r calc(g * 2) 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple b calc(r * .5) 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% 40% 60% / 80%) r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(none none none) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(none none none / none) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% none 60%) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% 40% 60% / none) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(from rebeccapurple h s l) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from color(display-p3 0 1 0) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lab(100% 104.3 -50.9) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lab(0% 104.3 -50.9) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lch(100% 116 334) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lch(0% 116 334) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklab(100% 0.365 -0.16) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklab(0% 0.365 -0.16) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklch(100% 0.399 336.3) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklch(0% 0.399 336.3) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0deg 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0deg 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0 s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0deg s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h 0% l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s 0% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s l / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 0 s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 0deg s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h 0% l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s 0% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s l / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 25 s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 25deg s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h 20% l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s l / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 25 s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 25deg s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h 20% l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s l / .2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h l s)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h alpha l / s)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h l l / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h l s)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h alpha l / s)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h l l / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple calc(h) calc(s) calc(l))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s l / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple none s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s l / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(none none none) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(none none none / none) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg none 50% / .5) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / none) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(none 20% 50% / .5) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(from rebeccapurple h w b) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from color(display-p3 0 1 0) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lab(100% 104.3 -50.9) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lab(0% 104.3 -50.9) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lch(100% 116 334) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lch(0% 116 334) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklab(100% 0.365 -0.16) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklab(0% 0.365 -0.16) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklch(100% 0.399 336.3) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklch(0% 0.399 336.3) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0deg 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0deg 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0 w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0deg w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h 0% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w 0% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 0 w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 0deg w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h 0% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w 0% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 25 w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 25deg w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w b / .2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 25 w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 25deg w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w b / .2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h b w)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h alpha w / b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w w / w)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h b w)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h alpha w / b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w w / w)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple calc(h) calc(w) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple none w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) h w b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(none none none) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(none none none / none) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg none 50% / .5) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / none) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(none 20% 50% / .5) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(200% 300 400 / 500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(-200% -300 -400 / -500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(from lab(25% 20 50) l a b) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from color(display-p3 0 0 0) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) 0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) 0% 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) 0% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) 0% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) 35% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l 35 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a 35 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b / .35)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) 35% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l 35 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a 35 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a b / .35)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) calc(l) calc(a) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(none none none) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(none none none / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% none 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(200% 300 400 / 500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(-200% -300 -400 / -500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(from oklab(25% 20 50) l a b) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from color(display-p3 0 0 0) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) 0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) 0% 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) 0% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) 0% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) 35% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l 35 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a 35 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b / .35)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) 35% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l 35 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a 35 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a b / .35)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) calc(l) calc(a) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(none none none) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(none none none / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% none 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(200% 300 400 / 500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(-200% -300 -400 / -500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(from lch(70% 45 30) l c h) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from color(display-p3 0 0 0) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lab(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 0% 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 0% 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 0% 0 0deg / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 0% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l 0 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c 0deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 0% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l 0 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c 0deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 25% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l 25 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c 25deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 25% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l 25 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 50% 120 400deg / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 50% 120 -400deg / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) alpha c h / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) alpha c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) alpha c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) alpha c h / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) alpha c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) alpha c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) calc(l) calc(c) calc(h))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(none none none) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(none none none / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% none 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(200% 300 400 / 500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(-200% -300 -400 / -500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(from oklch(70% 45 30) l c h) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from color(display-p3 0 0 0) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklab(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 0% 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 0% 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 0% 0 0deg / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 0% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l 0 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c 0deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 0% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l 0 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c 0deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 25% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l 25 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c 25deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 25% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l 25 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c 25deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 50% 120 400deg / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 50% 120 -400deg / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) alpha c h / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) alpha c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) alpha c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) alpha c h / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) alpha c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) alpha c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) calc(l) calc(c) calc(h))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(none none none) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(none none none / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% none 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(srgb 0.7 0.5 0.3) srgb r g b) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb none none none) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb none none none / none) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 none 0.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / none) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear none none none) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear none none none / none) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 none 0.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / none) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb none none none) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb none none none / none) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 none 0.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / none) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 none none none) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 none none none / none) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 none 0.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / none) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb none none none) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb none none none / none) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 none 0.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / none) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(xyz 7 -20.5 100) xyz x y z) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz calc(x) calc(y) calc(z))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz calc(x) calc(y) calc(z) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz none none none) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz none none none / none) xyz x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 none 100) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / none) xyz x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 calc(x) calc(y) calc(z))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 calc(x) calc(y) calc(z) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 none none none) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 none none none / none) xyz-d50 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 none 100) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / none) xyz-d50 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 calc(x) calc(y) calc(z))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 calc(x) calc(y) calc(z) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 none none none) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 none 100) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "rgb(from var(--bg-color) r g b / 80%)" should set the property value +PASS e.style['color'] = "lch(from var(--color) calc(l / 2) c h)" should set the property value +PASS e.style['color'] = "rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))" should set the property value +PASS e.style['color'] = "lch(from var(--color) l 0 h)" should set the property value +FAIL e.style['color'] = "rgb(from indianred 255 g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(from var(--accent) calc(h + 180deg) s l)" should set the property value +PASS e.style['color'] = "lab(from var(--mycolor) l a b / 100%)" should set the property value +PASS e.style['color'] = "lab(from var(--mycolor) l a b / calc(alpha * 0.8))" should set the property value +PASS e.style['color'] = "lab(from var(--mycolor) l a b / calc(alpha - 20%))" should set the property value +PASS e.style['color'] = "lab(from var(--mycolor) l 0 0)" should set the property value +FAIL e.style['color'] = "lch(from peru calc(l * 0.8) c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "LCH(from var(--accent) l c calc(h + 180deg))" should set the property value +PASS e.style['color'] = "lch(from var(--mycolor) l 0 h)" should set the property value +PASS e.style['color'] = "var(--mygray)" should set the property value +PASS e.style['color'] = "lch(from var(--mygray) l 30 h)" should set the property value +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-computed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-computed-expected.txt new file mode 100644 index 0000000..d290173 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-computed-expected.txt
@@ -0,0 +1,407 @@ +This is a testharness.js-based test. +Found 403 tests; 27 PASS, 376 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS Property color value 'currentcolor' +PASS Property color value 'transparent' +PASS Property color value 'red' +PASS Property color value 'magenta' +PASS Property color value '#234' +PASS Property color value '#FEDCBA' +PASS Property color value 'rgb(2, 3, 4)' +PASS Property color value 'rgb(100%, 0%, 0%)' +PASS Property color value 'rgba(2, 3, 4, 0.5)' +PASS Property color value 'rgba(2, 3, 4, 50%)' +PASS Property color value 'hsl(120, 100%, 50%)' +PASS Property color value 'hsla(120, 100%, 50%, 0.25)' +PASS Property color value 'rgb(-2, 3, 4)' +PASS Property color value 'rgb(100, 200, 300)' +PASS Property color value 'rgb(20, 10, 0, -10)' +PASS Property color value 'rgb(100%, 200%, 300%)' +FAIL Property color value 'rgb(none none none)' assert_true: 'rgb(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(none none none / none)' assert_true: 'rgb(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(128 none none)' assert_true: 'rgb(128 none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(128 none none / none)' assert_true: 'rgb(128 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(none none none / .5)' assert_true: 'rgb(none none none / .5)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(20% none none)' assert_true: 'rgb(20% none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(20% none none / none)' assert_true: 'rgb(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(none none none / 50%)' assert_true: 'rgb(none none none / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none)' assert_true: 'rgba(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none / none)' assert_true: 'rgba(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(128 none none)' assert_true: 'rgba(128 none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(128 none none / none)' assert_true: 'rgba(128 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none / .5)' assert_true: 'rgba(none none none / .5)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(20% none none)' assert_true: 'rgba(20% none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(20% none none / none)' assert_true: 'rgba(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgba(none none none / 50%)' assert_true: 'rgba(none none none / 50%)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 30% 50%)' +PASS Property color value 'hsl(120 30% 50% / 0.5)' +FAIL Property color value 'hsl(none none none)' assert_true: 'hsl(none none none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(0 0% 0%)' +FAIL Property color value 'hsl(none none none / none)' assert_true: 'hsl(none none none / none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(0 0% 0% / 0)' +FAIL Property color value 'hsla(none none none)' assert_true: 'hsla(none none none)' is a supported value for color. expected true got false +PASS Property color value 'hsla(0 0% 0%)' +FAIL Property color value 'hsla(none none none / none)' assert_true: 'hsla(none none none / none)' is a supported value for color. expected true got false +PASS Property color value 'hsla(0 0% 0% / 0)' +FAIL Property color value 'hsl(120 none none)' assert_true: 'hsl(120 none none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 0% 0%)' +FAIL Property color value 'hsl(120 80% none)' assert_true: 'hsl(120 80% none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 80% 0%)' +FAIL Property color value 'hsl(120 none 50%)' assert_true: 'hsl(120 none 50%)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 0% 50%)' +FAIL Property color value 'hsl(120 100% 50% / none)' assert_true: 'hsl(120 100% 50% / none)' is a supported value for color. expected true got false +PASS Property color value 'hsl(120 100% 50% / 0)' +FAIL Property color value 'hsl(none 100% 50%)' assert_true: 'hsl(none 100% 50%)' is a supported value for color. expected true got false +PASS Property color value 'hsl(0 100% 50%)' +FAIL Property color value 'hwb(120 30% 50%)' assert_true: 'hwb(120 30% 50%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 30% 50% / 0.5)' assert_true: 'hwb(120 30% 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(none none none)' assert_true: 'hwb(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(0 0% 0%)' assert_true: 'hwb(0 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(none none none / none)' assert_true: 'hwb(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(0 0% 0% / 0)' assert_true: 'hwb(0 0% 0% / 0)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 none none)' assert_true: 'hwb(120 none none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 0% 0%)' assert_true: 'hwb(120 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 80% none)' assert_true: 'hwb(120 80% none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 80% 0%)' assert_true: 'hwb(120 80% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 none 50%)' assert_true: 'hwb(120 none 50%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 0% 50%)' assert_true: 'hwb(120 0% 50%)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 30% 50% / none)' assert_true: 'hwb(120 30% 50% / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(120 30% 50% / 0)' assert_true: 'hwb(120 30% 50% / 0)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(none 100% 50% / none)' assert_true: 'hwb(none 100% 50% / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(0 100% 50% / 0)' assert_true: 'hwb(0 100% 50% / 0)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0% 0% 0%)' assert_true: 'color(srgb 0% 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 10% 10% 10%)' assert_true: 'color(srgb 10% 10% 10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb .2 .2 25%)' assert_true: 'color(srgb .2 .2 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0 0 0 / 1)' assert_true: 'color(srgb 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0% 0 0 / 0.5)' assert_true: 'color(srgb 0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 20% 0 10/0.5)' assert_true: 'color(srgb 20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 20% 0 10/50%)' assert_true: 'color(srgb 20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 400% 0 10/50%)' assert_true: 'color(srgb 400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50% -160 160)' assert_true: 'color(srgb 50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50% -200 200)' assert_true: 'color(srgb 50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0 0 0 / -10%)' assert_true: 'color(srgb 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0 0 0 / 110%)' assert_true: 'color(srgb 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0 0 0 / 300%)' assert_true: 'color(srgb 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50% -200)' assert_true: 'color(srgb 50% -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50%)' assert_true: 'color(srgb 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb)' assert_true: 'color(srgb)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50% -200 / 0.5)' assert_true: 'color(srgb 50% -200 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 50% / 0.5)' assert_true: 'color(srgb 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb / 0.5)' assert_true: 'color(srgb / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200 200 200)' assert_true: 'color(srgb 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200 200 200 / 200)' assert_true: 'color(srgb 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb -200 -200 -200)' assert_true: 'color(srgb -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb -200 -200 -200 / -200)' assert_true: 'color(srgb -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200% 200% 200%)' assert_true: 'color(srgb 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 200% 200% 200% / 200%)' assert_true: 'color(srgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb -200% -200% -200% / -200%)' assert_true: 'color(srgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb none none none / none)' assert_true: 'color(srgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb none none none)' assert_true: 'color(srgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 10% none none / none)' assert_true: 'color(srgb 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb none none none / 0.5)' assert_true: 'color(srgb none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb 0 0 0 / none)' assert_true: 'color(srgb 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0% 0% 0%)' assert_true: 'color(srgb-linear 0% 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 10% 10% 10%)' assert_true: 'color(srgb-linear 10% 10% 10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear .2 .2 25%)' assert_true: 'color(srgb-linear .2 .2 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0 0 0 / 1)' assert_true: 'color(srgb-linear 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0% 0 0 / 0.5)' assert_true: 'color(srgb-linear 0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 20% 0 10/0.5)' assert_true: 'color(srgb-linear 20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 20% 0 10/50%)' assert_true: 'color(srgb-linear 20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 400% 0 10/50%)' assert_true: 'color(srgb-linear 400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50% -160 160)' assert_true: 'color(srgb-linear 50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50% -200 200)' assert_true: 'color(srgb-linear 50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0 0 0 / -10%)' assert_true: 'color(srgb-linear 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0 0 0 / 110%)' assert_true: 'color(srgb-linear 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0 0 0 / 300%)' assert_true: 'color(srgb-linear 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50% -200)' assert_true: 'color(srgb-linear 50% -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50%)' assert_true: 'color(srgb-linear 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear)' assert_true: 'color(srgb-linear)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50% -200 / 0.5)' assert_true: 'color(srgb-linear 50% -200 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 50% / 0.5)' assert_true: 'color(srgb-linear 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear / 0.5)' assert_true: 'color(srgb-linear / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200 200 200)' assert_true: 'color(srgb-linear 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200 200 200 / 200)' assert_true: 'color(srgb-linear 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear -200 -200 -200)' assert_true: 'color(srgb-linear -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear -200 -200 -200 / -200)' assert_true: 'color(srgb-linear -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200% 200% 200%)' assert_true: 'color(srgb-linear 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 200% 200% 200% / 200%)' assert_true: 'color(srgb-linear 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear -200% -200% -200% / -200%)' assert_true: 'color(srgb-linear -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear none none none / none)' assert_true: 'color(srgb-linear none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear none none none)' assert_true: 'color(srgb-linear none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 10% none none / none)' assert_true: 'color(srgb-linear 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear none none none / 0.5)' assert_true: 'color(srgb-linear none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(srgb-linear 0 0 0 / none)' assert_true: 'color(srgb-linear 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0% 0% 0%)' assert_true: 'color(a98-rgb 0% 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 10% 10% 10%)' assert_true: 'color(a98-rgb 10% 10% 10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb .2 .2 25%)' assert_true: 'color(a98-rgb .2 .2 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0 0 0 / 1)' assert_true: 'color(a98-rgb 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0% 0 0 / 0.5)' assert_true: 'color(a98-rgb 0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 20% 0 10/0.5)' assert_true: 'color(a98-rgb 20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 20% 0 10/50%)' assert_true: 'color(a98-rgb 20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 400% 0 10/50%)' assert_true: 'color(a98-rgb 400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50% -160 160)' assert_true: 'color(a98-rgb 50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50% -200 200)' assert_true: 'color(a98-rgb 50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0 0 0 / -10%)' assert_true: 'color(a98-rgb 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0 0 0 / 110%)' assert_true: 'color(a98-rgb 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0 0 0 / 300%)' assert_true: 'color(a98-rgb 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50% -200)' assert_true: 'color(a98-rgb 50% -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50%)' assert_true: 'color(a98-rgb 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb)' assert_true: 'color(a98-rgb)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50% -200 / 0.5)' assert_true: 'color(a98-rgb 50% -200 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 50% / 0.5)' assert_true: 'color(a98-rgb 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb / 0.5)' assert_true: 'color(a98-rgb / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200 200 200)' assert_true: 'color(a98-rgb 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200 200 200 / 200)' assert_true: 'color(a98-rgb 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb -200 -200 -200)' assert_true: 'color(a98-rgb -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb -200 -200 -200 / -200)' assert_true: 'color(a98-rgb -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200% 200% 200%)' assert_true: 'color(a98-rgb 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 200% 200% 200% / 200%)' assert_true: 'color(a98-rgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb -200% -200% -200% / -200%)' assert_true: 'color(a98-rgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb none none none / none)' assert_true: 'color(a98-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb none none none)' assert_true: 'color(a98-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 10% none none / none)' assert_true: 'color(a98-rgb 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb none none none / 0.5)' assert_true: 'color(a98-rgb none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(a98-rgb 0 0 0 / none)' assert_true: 'color(a98-rgb 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0% 0% 0%)' assert_true: 'color(rec2020 0% 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 10% 10% 10%)' assert_true: 'color(rec2020 10% 10% 10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 .2 .2 25%)' assert_true: 'color(rec2020 .2 .2 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0 0 0 / 1)' assert_true: 'color(rec2020 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0% 0 0 / 0.5)' assert_true: 'color(rec2020 0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 20% 0 10/0.5)' assert_true: 'color(rec2020 20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 20% 0 10/50%)' assert_true: 'color(rec2020 20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 400% 0 10/50%)' assert_true: 'color(rec2020 400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50% -160 160)' assert_true: 'color(rec2020 50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50% -200 200)' assert_true: 'color(rec2020 50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0 0 0 / -10%)' assert_true: 'color(rec2020 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0 0 0 / 110%)' assert_true: 'color(rec2020 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0 0 0 / 300%)' assert_true: 'color(rec2020 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50% -200)' assert_true: 'color(rec2020 50% -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50%)' assert_true: 'color(rec2020 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020)' assert_true: 'color(rec2020)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50% -200 / 0.5)' assert_true: 'color(rec2020 50% -200 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 50% / 0.5)' assert_true: 'color(rec2020 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 / 0.5)' assert_true: 'color(rec2020 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200 200 200)' assert_true: 'color(rec2020 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200 200 200 / 200)' assert_true: 'color(rec2020 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 -200 -200 -200)' assert_true: 'color(rec2020 -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 -200 -200 -200 / -200)' assert_true: 'color(rec2020 -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200% 200% 200%)' assert_true: 'color(rec2020 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 200% 200% 200% / 200%)' assert_true: 'color(rec2020 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 -200% -200% -200% / -200%)' assert_true: 'color(rec2020 -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 none none none / none)' assert_true: 'color(rec2020 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 none none none)' assert_true: 'color(rec2020 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 10% none none / none)' assert_true: 'color(rec2020 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 none none none / 0.5)' assert_true: 'color(rec2020 none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(rec2020 0 0 0 / none)' assert_true: 'color(rec2020 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0% 0% 0%)' assert_true: 'color(prophoto-rgb 0% 0% 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 10% 10% 10%)' assert_true: 'color(prophoto-rgb 10% 10% 10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb .2 .2 25%)' assert_true: 'color(prophoto-rgb .2 .2 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0 0 0 / 1)' assert_true: 'color(prophoto-rgb 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0% 0 0 / 0.5)' assert_true: 'color(prophoto-rgb 0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 20% 0 10/0.5)' assert_true: 'color(prophoto-rgb 20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 20% 0 10/50%)' assert_true: 'color(prophoto-rgb 20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 400% 0 10/50%)' assert_true: 'color(prophoto-rgb 400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50% -160 160)' assert_true: 'color(prophoto-rgb 50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50% -200 200)' assert_true: 'color(prophoto-rgb 50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0 0 0 / -10%)' assert_true: 'color(prophoto-rgb 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0 0 0 / 110%)' assert_true: 'color(prophoto-rgb 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0 0 0 / 300%)' assert_true: 'color(prophoto-rgb 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50% -200)' assert_true: 'color(prophoto-rgb 50% -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50%)' assert_true: 'color(prophoto-rgb 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb)' assert_true: 'color(prophoto-rgb)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50% -200 / 0.5)' assert_true: 'color(prophoto-rgb 50% -200 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 50% / 0.5)' assert_true: 'color(prophoto-rgb 50% / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb / 0.5)' assert_true: 'color(prophoto-rgb / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200 200 200)' assert_true: 'color(prophoto-rgb 200 200 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200 200 200 / 200)' assert_true: 'color(prophoto-rgb 200 200 200 / 200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb -200 -200 -200)' assert_true: 'color(prophoto-rgb -200 -200 -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb -200 -200 -200 / -200)' assert_true: 'color(prophoto-rgb -200 -200 -200 / -200)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200% 200% 200%)' assert_true: 'color(prophoto-rgb 200% 200% 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 200% 200% 200% / 200%)' assert_true: 'color(prophoto-rgb 200% 200% 200% / 200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb -200% -200% -200% / -200%)' assert_true: 'color(prophoto-rgb -200% -200% -200% / -200%)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' assert_true: 'color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb none none none / none)' assert_true: 'color(prophoto-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb none none none)' assert_true: 'color(prophoto-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 10% none none / none)' assert_true: 'color(prophoto-rgb 10% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb none none none / 0.5)' assert_true: 'color(prophoto-rgb none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(prophoto-rgb 0 0 0 / none)' assert_true: 'color(prophoto-rgb 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0)' assert_true: 'color(xyz 0 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / 1)' assert_true: 'color(xyz 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1 1 1)' assert_true: 'color(xyz 1 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1 1 1 / 1)' assert_true: 'color(xyz 1 1 1 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz -1 -1 -1)' assert_true: 'color(xyz -1 -1 -1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0.1 0.1 0.1)' assert_true: 'color(xyz 0.1 0.1 0.1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 10 10 10)' assert_true: 'color(xyz 10 10 10)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz .2 .2 .25)' assert_true: 'color(xyz .2 .2 .25)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / 0.5)' assert_true: 'color(xyz 0 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz .20 0 10/0.5)' assert_true: 'color(xyz .20 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz .20 0 10/50%)' assert_true: 'color(xyz .20 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / -10%)' assert_true: 'color(xyz 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / 110%)' assert_true: 'color(xyz 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / 300%)' assert_true: 'color(xyz 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1 1)' assert_true: 'color(xyz 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1)' assert_true: 'color(xyz 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz)' assert_true: 'color(xyz)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1 1 / .5)' assert_true: 'color(xyz 1 1 / .5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 1 / 0.5)' assert_true: 'color(xyz 1 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz / 50%)' assert_true: 'color(xyz / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz none none none / none)' assert_true: 'color(xyz none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz none none none)' assert_true: 'color(xyz none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0.2 none none / none)' assert_true: 'color(xyz 0.2 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz none none none / 0.5)' assert_true: 'color(xyz none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz 0 0 0 / none)' assert_true: 'color(xyz 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0)' assert_true: 'color(xyz-d50 0 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / 1)' assert_true: 'color(xyz-d50 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1 1 1)' assert_true: 'color(xyz-d50 1 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1 1 1 / 1)' assert_true: 'color(xyz-d50 1 1 1 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 -1 -1 -1)' assert_true: 'color(xyz-d50 -1 -1 -1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0.1 0.1 0.1)' assert_true: 'color(xyz-d50 0.1 0.1 0.1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 10 10 10)' assert_true: 'color(xyz-d50 10 10 10)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 .2 .2 .25)' assert_true: 'color(xyz-d50 .2 .2 .25)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / 0.5)' assert_true: 'color(xyz-d50 0 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 .20 0 10/0.5)' assert_true: 'color(xyz-d50 .20 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 .20 0 10/50%)' assert_true: 'color(xyz-d50 .20 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / -10%)' assert_true: 'color(xyz-d50 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / 110%)' assert_true: 'color(xyz-d50 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / 300%)' assert_true: 'color(xyz-d50 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1 1)' assert_true: 'color(xyz-d50 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1)' assert_true: 'color(xyz-d50 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50)' assert_true: 'color(xyz-d50)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1 1 / .5)' assert_true: 'color(xyz-d50 1 1 / .5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 1 / 0.5)' assert_true: 'color(xyz-d50 1 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 / 50%)' assert_true: 'color(xyz-d50 / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 none none none / none)' assert_true: 'color(xyz-d50 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 none none none)' assert_true: 'color(xyz-d50 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0.2 none none / none)' assert_true: 'color(xyz-d50 0.2 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 none none none / 0.5)' assert_true: 'color(xyz-d50 none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d50 0 0 0 / none)' assert_true: 'color(xyz-d50 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0)' assert_true: 'color(xyz-d65 0 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / 1)' assert_true: 'color(xyz-d65 0 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1 1 1)' assert_true: 'color(xyz-d65 1 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1 1 1 / 1)' assert_true: 'color(xyz-d65 1 1 1 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 -1 -1 -1)' assert_true: 'color(xyz-d65 -1 -1 -1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0.1 0.1 0.1)' assert_true: 'color(xyz-d65 0.1 0.1 0.1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 10 10 10)' assert_true: 'color(xyz-d65 10 10 10)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 .2 .2 .25)' assert_true: 'color(xyz-d65 .2 .2 .25)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / 0.5)' assert_true: 'color(xyz-d65 0 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 .20 0 10/0.5)' assert_true: 'color(xyz-d65 .20 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 .20 0 10/50%)' assert_true: 'color(xyz-d65 .20 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / -10%)' assert_true: 'color(xyz-d65 0 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / 110%)' assert_true: 'color(xyz-d65 0 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / 300%)' assert_true: 'color(xyz-d65 0 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1 1)' assert_true: 'color(xyz-d65 1 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1)' assert_true: 'color(xyz-d65 1)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65)' assert_true: 'color(xyz-d65)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1 1 / .5)' assert_true: 'color(xyz-d65 1 1 / .5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 1 / 0.5)' assert_true: 'color(xyz-d65 1 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 / 50%)' assert_true: 'color(xyz-d65 / 50%)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' assert_true: 'color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 none none none / none)' assert_true: 'color(xyz-d65 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 none none none)' assert_true: 'color(xyz-d65 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0.2 none none / none)' assert_true: 'color(xyz-d65 0.2 none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 none none none / 0.5)' assert_true: 'color(xyz-d65 none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'color(xyz-d65 0 0 0 / none)' assert_true: 'color(xyz-d65 0 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0)' assert_true: 'lab(0% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / 1)' assert_true: 'lab(0% 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / 0.5)' assert_true: 'lab(0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lab(20% 0 10/0.5)' assert_true: 'lab(20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lab(20% 0 10/50%)' assert_true: 'lab(20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'lab(400% 0 10/50%)' assert_true: 'lab(400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'lab(50% -160 160)' assert_true: 'lab(50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'lab(50% -200 200)' assert_true: 'lab(50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / -10%)' assert_true: 'lab(0% 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / 110%)' assert_true: 'lab(0% 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / 300%)' assert_true: 'lab(0% 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'lab(-40% 0 0)' assert_true: 'lab(-40% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'lab(50% -20 0)' assert_true: 'lab(50% -20 0)' is a supported value for color. expected true got false +FAIL Property color value 'lab(50% 0 -20)' assert_true: 'lab(50% 0 -20)' is a supported value for color. expected true got false +FAIL Property color value 'lab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' assert_true: 'lab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'lab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' assert_true: 'lab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'lab(none none none / none)' assert_true: 'lab(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(none none none)' assert_true: 'lab(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(20% none none / none)' assert_true: 'lab(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(none none none / 0.5)' assert_true: 'lab(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lab(0% 0 0 / none)' assert_true: 'lab(0% 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0)' assert_true: 'oklab(0% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / 1)' assert_true: 'oklab(0% 0 0 / 1)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / 0.5)' assert_true: 'oklab(0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(20% 0 10/0.5)' assert_true: 'oklab(20% 0 10/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(20% 0 10/50%)' assert_true: 'oklab(20% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(400% 0 10/50%)' assert_true: 'oklab(400% 0 10/50%)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(50% -160 160)' assert_true: 'oklab(50% -160 160)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(50% -200 200)' assert_true: 'oklab(50% -200 200)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / -10%)' assert_true: 'oklab(0% 0 0 / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / 110%)' assert_true: 'oklab(0% 0 0 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / 300%)' assert_true: 'oklab(0% 0 0 / 300%)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(-40% 0 0)' assert_true: 'oklab(-40% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(50% -20 0)' assert_true: 'oklab(50% -20 0)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(50% 0 -20)' assert_true: 'oklab(50% 0 -20)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' assert_true: 'oklab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'oklab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' assert_true: 'oklab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'oklab(none none none / none)' assert_true: 'oklab(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(none none none)' assert_true: 'oklab(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(20% none none / none)' assert_true: 'oklab(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(none none none / 0.5)' assert_true: 'oklab(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(0% 0 0 / none)' assert_true: 'oklab(0% 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(0% 0 0deg)' assert_true: 'lch(0% 0 0deg)' is a supported value for color. expected true got false +FAIL Property color value 'lch(0% 0 0deg / 1)' assert_true: 'lch(0% 0 0deg / 1)' is a supported value for color. expected true got false +FAIL Property color value 'lch(0% 0 0deg / 0.5)' assert_true: 'lch(0% 0 0deg / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lch(100% 230 0deg / 0.5)' assert_true: 'lch(100% 230 0deg / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lch(20% 50 20deg/0.5)' assert_true: 'lch(20% 50 20deg/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lch(20% 50 20deg/50%)' assert_true: 'lch(20% 50 20deg/50%)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 20deg / -10%)' assert_true: 'lch(10% 20 20deg / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 20deg / 110%)' assert_true: 'lch(10% 20 20deg / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 1.28rad)' assert_true: 'lch(10% 20 1.28rad)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 380deg)' assert_true: 'lch(10% 20 380deg)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 -340deg)' assert_true: 'lch(10% 20 -340deg)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 740deg)' assert_true: 'lch(10% 20 740deg)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 -700deg)' assert_true: 'lch(10% 20 -700deg)' is a supported value for color. expected true got false +FAIL Property color value 'lch(-40% 0 0)' assert_true: 'lch(-40% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'lch(20% -20 0)' assert_true: 'lch(20% -20 0)' is a supported value for color. expected true got false +FAIL Property color value 'lch(0% 0 0 / 0.5)' assert_true: 'lch(0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 20 / 110%)' assert_true: 'lch(10% 20 20 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'lch(10% 20 -700)' assert_true: 'lch(10% 20 -700)' is a supported value for color. expected true got false +FAIL Property color value 'lch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' assert_true: 'lch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'lch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' assert_true: 'lch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'lch(none none none / none)' assert_true: 'lch(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(none none none)' assert_true: 'lch(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(20% none none / none)' assert_true: 'lch(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(none none none / 0.5)' assert_true: 'lch(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'lch(0% 0 0 / none)' assert_true: 'lch(0% 0 0 / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(0% 0 0deg)' assert_true: 'oklch(0% 0 0deg)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(0% 0 0deg / 1)' assert_true: 'oklch(0% 0 0deg / 1)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(0% 0 0deg / 0.5)' assert_true: 'oklch(0% 0 0deg / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(100% 230 0deg / 0.5)' assert_true: 'oklch(100% 230 0deg / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(20% 50 20deg/0.5)' assert_true: 'oklch(20% 50 20deg/0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(20% 50 20deg/50%)' assert_true: 'oklch(20% 50 20deg/50%)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 20deg / -10%)' assert_true: 'oklch(10% 20 20deg / -10%)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 20deg / 110%)' assert_true: 'oklch(10% 20 20deg / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 1.28rad)' assert_true: 'oklch(10% 20 1.28rad)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 380deg)' assert_true: 'oklch(10% 20 380deg)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 -340deg)' assert_true: 'oklch(10% 20 -340deg)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 740deg)' assert_true: 'oklch(10% 20 740deg)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 -700deg)' assert_true: 'oklch(10% 20 -700deg)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(-40% 0 0)' assert_true: 'oklch(-40% 0 0)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(20% -20 0)' assert_true: 'oklch(20% -20 0)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(0% 0 0 / 0.5)' assert_true: 'oklch(0% 0 0 / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 20 / 110%)' assert_true: 'oklch(10% 20 20 / 110%)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(10% 20 -700)' assert_true: 'oklch(10% 20 -700)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' assert_true: 'oklch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))' is a supported value for color. expected true got false +FAIL Property color value 'oklch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' assert_true: 'oklch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))' is a supported value for color. expected true got false +FAIL Property color value 'oklch(none none none / none)' assert_true: 'oklch(none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(none none none)' assert_true: 'oklch(none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(20% none none / none)' assert_true: 'oklch(20% none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(none none none / 0.5)' assert_true: 'oklch(none none none / 0.5)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(0% 0 0 / none)' assert_true: 'oklch(0% 0 0 / none)' is a supported value for color. expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-mix-computed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-mix-computed-expected.txt new file mode 100644 index 0000000..b9c96909 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-mix-computed-expected.txt
@@ -0,0 +1,478 @@ +This is a testharness.js-based test. +Found 474 tests; 0 PASS, 474 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%)' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8))' assert_true: 'color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' assert_true: 'color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(none none none), hsl(none none none))' assert_true: 'color-mix(in hsl, hsl(none none none), hsl(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))' assert_true: 'color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))' assert_true: 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))' assert_true: 'color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))' assert_true: 'color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))' assert_true: 'color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))' assert_true: 'color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%)' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' assert_true: 'color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(none none none), hwb(none none none))' assert_true: 'color-mix(in hwb, hwb(none none none), hwb(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))' assert_true: 'color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))' assert_true: 'color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' assert_true: 'color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, 25% lch(10% 20 30deg), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, 25% lch(10% 20 30deg), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), 25% lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg), 25% lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg) 25%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg) 75%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg) 30%, lch(50% 60 70deg) 90%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg) 30%, lch(50% 60 70deg) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg) 12.5%, lch(50% 60 70deg) 37.5%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg) 12.5%, lch(50% 60 70deg) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg) 0%, lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg) 0%, lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, 25% lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))' assert_true: 'color-mix(in lch, 25% lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4), 25% lch(50% 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4), 25% lch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) 25%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8) 75%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4) 30%, lch(50% 60 70deg / .8) 90%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4) 30%, lch(50% 60 70deg / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4) 12.5%, lch(50% 60 70deg / .8) 37.5%)' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4) 12.5%, lch(50% 60 70deg / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch shorter hue, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch shorter hue, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch longer hue, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch longer hue, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch increasing hue, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch increasing hue, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch decreasing hue, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch decreasing hue, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 40deg), lch(100% 0 60deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 40deg), lch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 60deg), lch(100% 0 40deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 60deg), lch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 50deg), lch(100% 0 330deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 50deg), lch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 330deg), lch(100% 0 50deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 330deg), lch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 20deg), lch(100% 0 320deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 20deg), lch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch specified hue, lch(100% 0 320deg), lch(100% 0 20deg))' assert_true: 'color-mix(in lch specified hue, lch(100% 0 320deg), lch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(none none none), lch(none none none))' assert_true: 'color-mix(in lch, lch(none none none), lch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(none none none), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(none none none), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(none none none))' assert_true: 'color-mix(in lch, lch(10% 20 30deg), lch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 none), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 none), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 none))' assert_true: 'color-mix(in lch, lch(10% 20 30deg), lch(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(none 20 30deg), lch(50% none 70deg))' assert_true: 'color-mix(in lch, lch(none 20 30deg), lch(50% none 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / 0.5))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / none))' assert_true: 'color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, 25% oklch(10% 20 30deg), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, 25% oklch(10% 20 30deg), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), 25% oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), 25% oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg) 25%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg) 75%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 30%, oklch(50% 60 70deg) 90%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg) 30%, oklch(50% 60 70deg) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 12.5%, oklch(50% 60 70deg) 37.5%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg) 12.5%, oklch(50% 60 70deg) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg) 0%, oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg) 0%, oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, 25% oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))' assert_true: 'color-mix(in oklch, 25% oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4), 25% oklch(50% 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4), 25% oklch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8) 25%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8) 75%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4) 30%, oklch(50% 60 70deg / .8) 90%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4) 30%, oklch(50% 60 70deg / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4) 12.5%, oklch(50% 60 70deg / .8) 37.5%)' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4) 12.5%, oklch(50% 60 70deg / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / .4) 0%, oklch(50% 60 70deg / .8))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / .4) 0%, oklch(50% 60 70deg / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch shorter hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch shorter hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch longer hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch longer hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch increasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch increasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch decreasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch decreasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 40deg), oklch(100% 0 60deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 60deg), oklch(100% 0 40deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 50deg), oklch(100% 0 330deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 330deg), oklch(100% 0 50deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 20deg), oklch(100% 0 320deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch specified hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' assert_true: 'color-mix(in oklch specified hue, oklch(100% 0 320deg), oklch(100% 0 20deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(none none none), oklch(none none none))' assert_true: 'color-mix(in oklch, oklch(none none none), oklch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(none none none), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(none none none), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(none none none))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), oklch(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 none), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 none), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 none))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(none 20 30deg), oklch(50% none 70deg))' assert_true: 'color-mix(in oklch, oklch(none 20 30deg), oklch(50% none 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / 0.5))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / none))' assert_true: 'color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, 25% lab(10% 20 30), lab(50% 60 70))' assert_true: 'color-mix(in lab, 25% lab(10% 20 30), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), 25% lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30), 25% lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), lab(50% 60 70) 25%)' assert_true: 'color-mix(in lab, lab(10% 20 30), lab(50% 60 70) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70) 75%)' assert_true: 'color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30) 30%, lab(50% 60 70) 90%)' assert_true: 'color-mix(in lab, lab(10% 20 30) 30%, lab(50% 60 70) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30) 12.5%, lab(50% 60 70) 37.5%)' assert_true: 'color-mix(in lab, lab(10% 20 30) 12.5%, lab(50% 60 70) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30) 0%, lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30) 0%, lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, 25% lab(10% 20 30 / .4), lab(50% 60 70 / .8))' assert_true: 'color-mix(in lab, 25% lab(10% 20 30 / .4), lab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4), 25% lab(50% 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4), 25% lab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) 25%)' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8) 75%)' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 30%, lab(50% 60 70 / .8) 90%)' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 30%, lab(50% 60 70 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))' assert_true: 'color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(none none none), lab(none none none))' assert_true: 'color-mix(in lab, lab(none none none), lab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(none none none), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(none none none), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), lab(none none none))' assert_true: 'color-mix(in lab, lab(10% 20 30), lab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 none), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 none), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30), lab(50% 60 none))' assert_true: 'color-mix(in lab, lab(10% 20 30), lab(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(none 20 30), lab(50% none 70))' assert_true: 'color-mix(in lab, lab(none 20 30), lab(50% none 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70))' assert_true: 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / 0.5))' assert_true: 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / none))' assert_true: 'color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, 25% oklab(10% 20 30), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, 25% oklab(10% 20 30), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), 25% oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30), 25% oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70) 25%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70) 75%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30) 30%, oklab(50% 60 70) 90%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30) 30%, oklab(50% 60 70) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30) 12.5%, oklab(50% 60 70) 37.5%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30) 12.5%, oklab(50% 60 70) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30) 0%, oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30) 0%, oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, 25% oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))' assert_true: 'color-mix(in oklab, 25% oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4), 25% oklab(50% 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4), 25% oklab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8) 25%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8) 75%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 30%, oklab(50% 60 70 / .8) 90%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 30%, oklab(50% 60 70 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 12.5%, oklab(50% 60 70 / .8) 37.5%)' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 12.5%, oklab(50% 60 70 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / .4) 0%, oklab(50% 60 70 / .8))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / .4) 0%, oklab(50% 60 70 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(none none none), oklab(none none none))' assert_true: 'color-mix(in oklab, oklab(none none none), oklab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(none none none), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(none none none), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(none none none))' assert_true: 'color-mix(in oklab, oklab(10% 20 30), oklab(none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 none), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 none), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 none))' assert_true: 'color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(none 20 30), oklab(50% none 70))' assert_true: 'color-mix(in oklab, oklab(none 20 30), oklab(50% none 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / 0.5))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / none))' assert_true: 'color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7) 25%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), 25% color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), 25% color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7) 75%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 30%, color(srgb .5 .6 .7) 90%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 30%, color(srgb .5 .6 .7) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 12.5%, color(srgb .5 .6 .7) 37.5%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 12.5%, color(srgb .5 .6 .7) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3) 0%, color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3) 0%, color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .5), color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .5), color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, 25% color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, 25% color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), 25% color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4), 25% color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))' assert_true: 'color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))' assert_true: 'color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))' assert_true: 'color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb none none none))' assert_true: 'color-mix(in srgb, color(srgb none none none), color(srgb none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))' assert_true: 'color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))' assert_true: 'color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7) 25%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), 25% color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), 25% color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7) 75%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 30%, color(srgb-linear .5 .6 .7) 90%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 30%, color(srgb-linear .5 .6 .7) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 12.5%, color(srgb-linear .5 .6 .7) 37.5%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 12.5%, color(srgb-linear .5 .6 .7) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 0%, color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 0%, color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .5), color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .5), color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), 25% color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), 25% color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))' assert_true: 'color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, 25% color(xyz .1 .2 .3), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, 25% color(xyz .1 .2 .3), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7) 25%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), 25% color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), 25% color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7) 75%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 30%, color(xyz .5 .6 .7) 90%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 30%, color(xyz .5 .6 .7) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 12.5%, color(xyz .5 .6 .7) 37.5%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 12.5%, color(xyz .5 .6 .7) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3) 0%, color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3) 0%, color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .5), color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .5), color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, 25% color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, 25% color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), 25% color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4), 25% color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))' assert_true: 'color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))' assert_true: 'color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz none none none))' assert_true: 'color-mix(in xyz, color(xyz none none none), color(xyz none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))' assert_true: 'color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))' assert_true: 'color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7) 25%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), 25% color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), 25% color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7) 75%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 30%, color(xyz-d50 .5 .6 .7) 90%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 30%, color(xyz-d50 .5 .6 .7) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 12.5%, color(xyz-d50 .5 .6 .7) 37.5%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 12.5%, color(xyz-d50 .5 .6 .7) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 0%, color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 0%, color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .5), color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .5), color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), 25% color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), 25% color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))' assert_true: 'color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7) 25%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), 25% color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), 25% color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7) 75%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 30%, color(xyz-d65 .5 .6 .7) 90%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 30%, color(xyz-d65 .5 .6 .7) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 12.5%, color(xyz-d65 .5 .6 .7) 37.5%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 12.5%, color(xyz-d65 .5 .6 .7) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 0%, color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 0%, color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .5), color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .5), color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8) 25%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8) 25%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), 25% color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), 25% color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8) 75%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8) 75%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))' is a supported value for color. expected true got false +FAIL Property color value 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))' assert_true: 'color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))' is a supported value for color. expected true got false +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-mix-valid-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-mix-valid-expected.txt new file mode 100644 index 0000000..3d1143a --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-mix-valid-expected.txt
@@ -0,0 +1,478 @@ +This is a testharness.js-based test. +Found 474 tests; 0 PASS, 474 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, 25% hsl(120deg 10% 20%), hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%), 25% hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%), hsl(30deg 30% 40%) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40%) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 30%, hsl(30deg 30% 40%) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 12.5%, hsl(30deg 30% 40%) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 0%, hsl(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20%) 25%, hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, 25% hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4), 25% hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4), hsl(30deg 30% 40% / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 25%, hsl(30deg 30% 40% / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 30%, hsl(30deg 30% 40% / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 12.5%, hsl(30deg 30% 40% / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 10% 20% / .4) 0%, hsl(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl shorter hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl longer hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl increasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl decreasing hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(40deg 50% 50%), hsl(60deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(60deg 50% 50%), hsl(40deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(50deg 50% 50%), hsl(330deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(330deg 50% 50%), hsl(50deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(20deg 50% 50%), hsl(320deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl specified hue, hsl(320deg 50% 50%), hsl(20deg 50% 50%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(none none none), hsl(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(none none none), hsl(30deg 40% 80%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% 40%), hsl(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% none), hsl(30deg 40% 60%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 20% 40%), hsl(30deg 20% none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(none 20% 40%), hsl(30deg none 80%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, hsl(120deg 40% 40% / none), hsl(0deg 40% 40% / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hsl, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, 25% hwb(120deg 10% 20%), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% 40%) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 25%, hwb(30deg 30% 40%) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 30%, hwb(30deg 30% 40%) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 12.5%, hwb(30deg 30% 40%) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%) 0%, hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, 25% hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), 25% hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4), hwb(30deg 30% 40% / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 25%, hwb(30deg 30% 40% / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 30%, hwb(30deg 30% 40% / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 12.5%, hwb(30deg 30% 40% / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / .4) 0%, hwb(30deg 30% 40% / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb shorter hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb longer hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb increasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb decreasing hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(40deg 30% 40%), hwb(60deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(60deg 30% 40%), hwb(40deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(50deg 30% 40%), hwb(330deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(330deg 30% 40%), hwb(50deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(20deg 30% 40%), hwb(320deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb specified hue, hwb(320deg 30% 40%), hwb(20deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(none none none), hwb(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(none none none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20%), hwb(30deg 30% none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(none 10% 20%), hwb(30deg none 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40%))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, hwb(120deg 10% 20% / none), hwb(30deg 30% 40% / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, color(display-p3 0 1 0) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lab(100% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lab(0% 104.3 -50.9) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lch(100% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, lch(0% 116 334) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklab(100% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklab(0% 0.365 -0.16) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklch(100% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in hwb, oklch(0% 0.399 336.3) 100%, rgb(0, 0, 0) 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, 25% lch(10% 20 30deg), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), 25% lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 70deg) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 25%, lch(50% 60 70deg) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 30%, lch(50% 60 70deg) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 12.5%, lch(50% 60 70deg) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg) 0%, lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, 25% lch(10% 20 30deg / .4), lch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4), 25% lch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4), lch(50% 60 70deg / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4) 25%, lch(50% 60 70deg / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4) 30%, lch(50% 60 70deg / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4) 12.5%, lch(50% 60 70deg / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / .4) 0%, lch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch shorter hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch longer hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch increasing hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch decreasing hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 40deg), lch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 60deg), lch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 50deg), lch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 330deg), lch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 20deg), lch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch specified hue, lch(100% 0 320deg), lch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(none none none), lch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(none none none), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 none), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg), lch(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(none 20 30deg), lch(50% none 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lch, lch(10% 20 30deg / none), lch(50% 60 70deg / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, 25% oklch(10% 20 30deg), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), 25% oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 70deg) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 25%, oklch(50% 60 70deg) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 30%, oklch(50% 60 70deg) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 12.5%, oklch(50% 60 70deg) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg) 0%, oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, 25% oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4), 25% oklch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4), oklch(50% 60 70deg / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4) 25%, oklch(50% 60 70deg / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4) 30%, oklch(50% 60 70deg / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4) 12.5%, oklch(50% 60 70deg / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / .4) 0%, oklch(50% 60 70deg / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch shorter hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch longer hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch increasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch decreasing hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 40deg), oklch(100% 0 60deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 60deg), oklch(100% 0 40deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 50deg), oklch(100% 0 330deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 330deg), oklch(100% 0 50deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 20deg), oklch(100% 0 320deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch specified hue, oklch(100% 0 320deg), oklch(100% 0 20deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(none none none), oklch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(none none none), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 none), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg), oklch(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(none 20 30deg), oklch(50% none 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklch, oklch(10% 20 30deg / none), oklch(50% 60 70deg / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, 25% lab(10% 20 30), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), 25% lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(50% 60 70) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30) 25%, lab(50% 60 70) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30) 30%, lab(50% 60 70) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30) 12.5%, lab(50% 60 70) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30) 0%, lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, 25% lab(10% 20 30 / .4), lab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4), 25% lab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4), lab(50% 60 70 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 25%, lab(50% 60 70 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 30%, lab(50% 60 70 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 12.5%, lab(50% 60 70 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / .4) 0%, lab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(none none none), lab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(none none none), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 none), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30), lab(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(none 20 30), lab(50% none 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in lab, lab(10% 20 30 / none), lab(50% 60 70 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, 25% oklab(10% 20 30), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), 25% oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 70) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 25%, oklab(50% 60 70) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 30%, oklab(50% 60 70) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 12.5%, oklab(50% 60 70) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30) 0%, oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, 25% oklab(10% 20 30 / .4), oklab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4), 25% oklab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4), oklab(50% 60 70 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 25%, oklab(50% 60 70 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 30%, oklab(50% 60 70 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 12.5%, oklab(50% 60 70 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / .4) 0%, oklab(50% 60 70 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(none none none), oklab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(none none none), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 none), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30), oklab(50% 60 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(none 20 30), oklab(50% none 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in oklab, oklab(10% 20 30 / none), oklab(50% 60 70 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, 25% color(srgb .1 .2 .3), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), 25% color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 25%, color(srgb .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 30%, color(srgb .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 12.5%, color(srgb .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3) 0%, color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .5), color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, 25% color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4), color(srgb .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4), 25% color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 25%, color(srgb .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 30%, color(srgb .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 12.5%, color(srgb .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / .4) 0%, color(srgb .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb 2 3 4 / 5), color(srgb 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb -2 -3 -4), color(srgb -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb -2 -3 -4 / -5), color(srgb -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb none none none), color(srgb none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb none none none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3), color(srgb .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb none .2 .3), color(srgb .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb, color(srgb .1 .2 .3 / none), color(srgb .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), 25% color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 25%, color(srgb-linear .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 30%, color(srgb-linear .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 12.5%, color(srgb-linear .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3) 0%, color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .5), color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, 25% color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), color(srgb-linear .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4), 25% color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 25%, color(srgb-linear .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 30%, color(srgb-linear .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 12.5%, color(srgb-linear .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / .4) 0%, color(srgb-linear .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear 2 3 4 / 5), color(srgb-linear 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear -2 -3 -4), color(srgb-linear -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear -2 -3 -4 / -5), color(srgb-linear -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none none none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3), color(srgb-linear .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear none .2 .3), color(srgb-linear .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in srgb-linear, color(srgb-linear .1 .2 .3 / none), color(srgb-linear .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, 25% color(xyz .1 .2 .3), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), 25% color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 25%, color(xyz .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 30%, color(xyz .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 12.5%, color(xyz .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3) 0%, color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .5), color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, 25% color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4), color(xyz .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4), 25% color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 25%, color(xyz .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 30%, color(xyz .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 12.5%, color(xyz .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / .4) 0%, color(xyz .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz 2 3 4 / 5), color(xyz 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz -2 -3 -4), color(xyz -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz -2 -3 -4 / -5), color(xyz -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz none none none), color(xyz none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz none none none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3), color(xyz .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz none .2 .3), color(xyz .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz, color(xyz .1 .2 .3 / none), color(xyz .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), 25% color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 25%, color(xyz-d50 .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 30%, color(xyz-d50 .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 12.5%, color(xyz-d50 .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3) 0%, color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .5), color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, 25% color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), color(xyz-d50 .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4), 25% color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 25%, color(xyz-d50 .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 30%, color(xyz-d50 .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 12.5%, color(xyz-d50 .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / .4) 0%, color(xyz-d50 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 2 3 4 / 5), color(xyz-d50 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4), color(xyz-d50 -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 -2 -3 -4 / -5), color(xyz-d50 -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none none none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3), color(xyz-d50 .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 none .2 .3), color(xyz-d50 .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d50, color(xyz-d50 .1 .2 .3 / none), color(xyz-d50 .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 .7) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), 25% color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 25%, color(xyz-d65 .5 .6 .7) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 30%, color(xyz-d65 .5 .6 .7) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 12.5%, color(xyz-d65 .5 .6 .7) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3) 0%, color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .5), color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, 25% color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), color(xyz-d65 .5 .6 .7 / .8) 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4), 25% color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 25%, color(xyz-d65 .5 .6 .7 / .8) 75%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 30%, color(xyz-d65 .5 .6 .7 / .8) 90%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 12.5%, color(xyz-d65 .5 .6 .7 / .8) 37.5%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / .4) 0%, color(xyz-d65 .5 .6 .7 / .8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 2 3 4 / 5), color(xyz-d65 4 6 8 / 10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4), color(xyz-d65 -4 -6 -8))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 -2 -3 -4 / -5), color(xyz-d65 -4 -6 -8 / -10))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none none none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 none none none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3), color(xyz-d65 .5 .6 none))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 none .2 .3), color(xyz-d65 .5 none .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / 0.5))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color-mix(in xyz-d65, color(xyz-d65 .1 .2 .3 / none), color(xyz-d65 .5 .6 .7 / none))" should set the property value assert_not_equals: property should be set got disallowed value "" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-valid-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-valid-expected.txt new file mode 100644 index 0000000..f1e4105 --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/color-valid-expected.txt
@@ -0,0 +1,407 @@ +This is a testharness.js-based test. +Found 403 tests; 27 PASS, 376 FAIL, 0 TIMEOUT, 0 NOTRUN. +PASS e.style['color'] = "currentcolor" should set the property value +PASS e.style['color'] = "transparent" should set the property value +PASS e.style['color'] = "red" should set the property value +PASS e.style['color'] = "magenta" should set the property value +PASS e.style['color'] = "#234" should set the property value +PASS e.style['color'] = "#FEDCBA" should set the property value +PASS e.style['color'] = "rgb(2, 3, 4)" should set the property value +PASS e.style['color'] = "rgb(100%, 0%, 0%)" should set the property value +PASS e.style['color'] = "rgba(2, 3, 4, 0.5)" should set the property value +PASS e.style['color'] = "rgba(2, 3, 4, 50%)" should set the property value +PASS e.style['color'] = "hsl(120, 100%, 50%)" should set the property value +PASS e.style['color'] = "hsla(120, 100%, 50%, 0.25)" should set the property value +PASS e.style['color'] = "rgb(-2, 3, 4)" should set the property value +PASS e.style['color'] = "rgb(100, 200, 300)" should set the property value +PASS e.style['color'] = "rgb(20, 10, 0, -10)" should set the property value +PASS e.style['color'] = "rgb(100%, 200%, 300%)" should set the property value +FAIL e.style['color'] = "rgb(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(128 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(128 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(none none none / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(20% none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(none none none / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(128 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(128 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(20% none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgba(none none none / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 30% 50%)" should set the property value +PASS e.style['color'] = "hsl(120 30% 50% / 0.5)" should set the property value +FAIL e.style['color'] = "hsl(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(0 0% 0%)" should set the property value +FAIL e.style['color'] = "hsl(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(0 0% 0% / 0)" should set the property value +FAIL e.style['color'] = "hsla(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsla(0 0% 0%)" should set the property value +FAIL e.style['color'] = "hsla(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsla(0 0% 0% / 0)" should set the property value +FAIL e.style['color'] = "hsl(120 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 0% 0%)" should set the property value +FAIL e.style['color'] = "hsl(120 80% none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 80% 0%)" should set the property value +FAIL e.style['color'] = "hsl(120 none 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 0% 50%)" should set the property value +FAIL e.style['color'] = "hsl(120 100% 50% / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(120 100% 50% / 0)" should set the property value +FAIL e.style['color'] = "hsl(none 100% 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(0 100% 50%)" should set the property value +FAIL e.style['color'] = "hwb(120 30% 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 30% 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(0 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(0 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 80% none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 80% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 none 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 0% 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 30% 50% / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(120 30% 50% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(none 100% 50% / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(0 100% 50% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(srgb-linear 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(a98-rgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(rec2020 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0% 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 10% 10% 10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb .2 .2 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50% -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50% -200 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 50% / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200 200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200 200 200 / 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb -200 -200 -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb -200 -200 -200 / -200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200% 200% 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 200% 200% 200% / 200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb -200% -200% -200% / -200%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb calc(50% * 3) calc(-150% / 3) calc(50%) / calc(-50% * 3))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 10% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(prophoto-rgb 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1 1 1 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz -1 -1 -1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0.1 0.1 0.1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 10 10 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz .2 .2 .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz .20 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz .20 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1 1 1 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 -1 -1 -1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0.1 0.1 0.1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 10 10 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 .2 .2 .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 .20 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 .20 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d50 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1 1 1 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 -1 -1 -1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0.1 0.1 0.1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 10 10 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 .2 .2 .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 .20 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 .20 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1 1 / .5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 1 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 / 50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 calc(0.5 + 1) calc(0.5 - 1) calc(0.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0.2 none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(xyz-d65 0 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(-40% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(50% -20 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(50% 0 -20)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(20% 0 10/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(20% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(400% 0 10/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(50% -160 160)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(50% -200 200)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / 300%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(-40% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(50% -20 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(50% 0 -20)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(calc(50% * 3) calc(0.5 - 1) calc(1.5) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(calc(-50% * 3) calc(0.5 + 1) calc(-1.5) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(0% 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(0% 0 0deg / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(0% 0 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(100% 230 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(20% 50 20deg/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(20% 50 20deg/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 20deg / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 20deg / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 1.28rad)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 380deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 -340deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 740deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 -700deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(-40% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(20% -20 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 20 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(10% 20 -700)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(0% 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(0% 0 0deg / 1)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(0% 0 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(100% 230 0deg / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(20% 50 20deg/0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(20% 50 20deg/50%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 20deg / -10%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 20deg / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 1.28rad)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 380deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 -340deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 740deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 -700deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(-40% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(20% -20 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(0% 0 0 / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 20 / 110%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(10% 20 -700)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(calc(50% * 3) calc(0.5 - 1) calc(20deg * 2) / calc(-0.5 + 1))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(calc(-50% * 3) calc(0.5 + 1) calc(-20deg * 2) / calc(-0.5 * 2))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(20% none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(none none none / 0.5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(0% 0 0 / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt similarity index 66% copy from third_party/blink/web_tests/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt copy to third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt index 6b9f5f9..a22d69e 100644 --- a/third_party/blink/web_tests/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-computed-expected.txt
@@ -1,11 +1,19 @@ This is a testharness.js-based test. -Found 586 tests; 0 PASS, 586 FAIL, 0 TIMEOUT, 0 NOTRUN. +Found 881 tests; 0 PASS, 881 FAIL, 0 TIMEOUT, 0 NOTRUN. FAIL Property color value 'rgb(from rebeccapurple r g b)' assert_true: 'rgb(from rebeccapurple r g b)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple r g b / alpha)' assert_true: 'rgb(from rebeccapurple r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)' assert_true: 'rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)' assert_true: 'rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rgb(from rebeccapurple r g b) r g b)' assert_true: 'rgb(from rgb(from rebeccapurple r g b) r g b)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from color(display-p3 0 1 0) r g b / alpha)' assert_true: 'rgb(from color(display-p3 0 1 0) r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lab(100% 104.3 -50.9) r g b)' assert_true: 'rgb(from lab(100% 104.3 -50.9) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lab(0% 104.3 -50.9) r g b)' assert_true: 'rgb(from lab(0% 104.3 -50.9) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lch(100% 116 334) r g b)' assert_true: 'rgb(from lch(100% 116 334) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from lch(0% 116 334) r g b)' assert_true: 'rgb(from lch(0% 116 334) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklab(100% 0.365 -0.16) r g b)' assert_true: 'rgb(from oklab(100% 0.365 -0.16) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklab(0% 0.365 -0.16) r g b)' assert_true: 'rgb(from oklab(0% 0.365 -0.16) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklch(100% 0.399 336.3) r g b)' assert_true: 'rgb(from oklch(100% 0.399 336.3) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from oklch(0% 0.399 336.3) r g b)' assert_true: 'rgb(from oklch(0% 0.399 336.3) r g b)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple 0 0 0)' assert_true: 'rgb(from rebeccapurple 0 0 0)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple 0 0 0 / 0)' assert_true: 'rgb(from rebeccapurple 0 0 0 / 0)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple 0 g b / alpha)' assert_true: 'rgb(from rebeccapurple 0 g b / alpha)' is a supported value for color. expected true got false @@ -58,12 +66,31 @@ FAIL Property color value 'rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)' assert_true: 'rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)' assert_true: 'rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple none none none)' assert_true: 'rgb(from rebeccapurple none none none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple none none none / none)' assert_true: 'rgb(from rebeccapurple none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple r g none)' assert_true: 'rgb(from rebeccapurple r g none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple r g none / alpha)' assert_true: 'rgb(from rebeccapurple r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rebeccapurple r g b / none)' assert_true: 'rgb(from rebeccapurple r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)' assert_true: 'rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% 40% 60% / 80%) r g b / none)' assert_true: 'rgb(from rgb(20% 40% 60% / 80%) r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(none none none) r g b)' assert_true: 'rgb(from rgb(none none none) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(none none none / none) r g b / alpha)' assert_true: 'rgb(from rgb(none none none / none) r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% none 60%) r g b)' assert_true: 'rgb(from rgb(20% none 60%) r g b)' is a supported value for color. expected true got false +FAIL Property color value 'rgb(from rgb(20% 40% 60% / none) r g b / alpha)' assert_true: 'rgb(from rgb(20% 40% 60% / none) r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple h s l)' assert_true: 'hsl(from rebeccapurple h s l)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple h s l / alpha)' assert_true: 'hsl(from rebeccapurple h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)' assert_true: 'hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from hsl(from rebeccapurple h s l) h s l)' assert_true: 'hsl(from hsl(from rebeccapurple h s l) h s l)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from color(display-p3 0 1 0) h s l / alpha)' assert_true: 'hsl(from color(display-p3 0 1 0) h s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lab(100% 104.3 -50.9) h s l)' assert_true: 'hsl(from lab(100% 104.3 -50.9) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lab(0% 104.3 -50.9) h s l)' assert_true: 'hsl(from lab(0% 104.3 -50.9) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lch(100% 116 334) h s l)' assert_true: 'hsl(from lch(100% 116 334) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from lch(0% 116 334) h s l)' assert_true: 'hsl(from lch(0% 116 334) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklab(100% 0.365 -0.16) h s l)' assert_true: 'hsl(from oklab(100% 0.365 -0.16) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklab(0% 0.365 -0.16) h s l)' assert_true: 'hsl(from oklab(0% 0.365 -0.16) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklch(100% 0.399 336.3) h s l)' assert_true: 'hsl(from oklch(100% 0.399 336.3) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from oklch(0% 0.399 336.3) h s l)' assert_true: 'hsl(from oklch(0% 0.399 336.3) h s l)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple 0 0% 0%)' assert_true: 'hsl(from rebeccapurple 0 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple 0deg 0% 0%)' assert_true: 'hsl(from rebeccapurple 0deg 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple 0 0% 0% / 0)' assert_true: 'hsl(from rebeccapurple 0 0% 0% / 0)' is a supported value for color. expected true got false @@ -98,12 +125,34 @@ FAIL Property color value 'hsl(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' assert_true: 'hsl(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rebeccapurple calc(h) calc(s) calc(l))' assert_true: 'hsl(from rebeccapurple calc(h) calc(s) calc(l))' is a supported value for color. expected true got false FAIL Property color value 'hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))' assert_true: 'hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple none none none)' assert_true: 'hsl(from rebeccapurple none none none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple none none none / none)' assert_true: 'hsl(from rebeccapurple none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple h s none)' assert_true: 'hsl(from rebeccapurple h s none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple h s none / alpha)' assert_true: 'hsl(from rebeccapurple h s none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple h s l / none)' assert_true: 'hsl(from rebeccapurple h s l / none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from rebeccapurple none s l / alpha)' assert_true: 'hsl(from rebeccapurple none s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) h s l / none)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) h s l / none)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(none none none) h s l)' assert_true: 'hsl(from hsl(none none none) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(none none none / none) h s l / alpha)' assert_true: 'hsl(from hsl(none none none / none) h s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg none 50% / .5) h s l)' assert_true: 'hsl(from hsl(120deg none 50% / .5) h s l)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(120deg 20% 50% / none) h s l / alpha)' assert_true: 'hsl(from hsl(120deg 20% 50% / none) h s l / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hsl(from hsl(none 20% 50% / .5) h s l / alpha)' assert_true: 'hsl(from hsl(none 20% 50% / .5) h s l / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple h w b)' assert_true: 'hwb(from rebeccapurple h w b)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple h w b / alpha)' assert_true: 'hwb(from rebeccapurple h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)' assert_true: 'hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)' assert_true: 'hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from hwb(from rebeccapurple h w b) h w b)' assert_true: 'hwb(from hwb(from rebeccapurple h w b) h w b)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from color(display-p3 0 1 0) h w b / alpha)' assert_true: 'hwb(from color(display-p3 0 1 0) h w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lab(100% 104.3 -50.9) h w b)' assert_true: 'hwb(from lab(100% 104.3 -50.9) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lab(0% 104.3 -50.9) h w b)' assert_true: 'hwb(from lab(0% 104.3 -50.9) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lch(100% 116 334) h w b)' assert_true: 'hwb(from lch(100% 116 334) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from lch(0% 116 334) h w b)' assert_true: 'hwb(from lch(0% 116 334) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklab(100% 0.365 -0.16) h w b)' assert_true: 'hwb(from oklab(100% 0.365 -0.16) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklab(0% 0.365 -0.16) h w b)' assert_true: 'hwb(from oklab(0% 0.365 -0.16) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklch(100% 0.399 336.3) h w b)' assert_true: 'hwb(from oklch(100% 0.399 336.3) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from oklch(0% 0.399 336.3) h w b)' assert_true: 'hwb(from oklch(0% 0.399 336.3) h w b)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple 0 0% 0%)' assert_true: 'hwb(from rebeccapurple 0 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple 0deg 0% 0%)' assert_true: 'hwb(from rebeccapurple 0deg 0% 0%)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple 0 0% 0% / 0)' assert_true: 'hwb(from rebeccapurple 0 0% 0% / 0)' is a supported value for color. expected true got false @@ -138,9 +187,25 @@ FAIL Property color value 'hwb(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' assert_true: 'hwb(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rebeccapurple calc(h) calc(w) calc(b))' assert_true: 'hwb(from rebeccapurple calc(h) calc(w) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))' assert_true: 'hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple none none none)' assert_true: 'hwb(from rebeccapurple none none none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple none none none / none)' assert_true: 'hwb(from rebeccapurple none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple h w none)' assert_true: 'hwb(from rebeccapurple h w none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple h w none / alpha)' assert_true: 'hwb(from rebeccapurple h w none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple h w b / none)' assert_true: 'hwb(from rebeccapurple h w b / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from rebeccapurple none w b / alpha)' assert_true: 'hwb(from rebeccapurple none w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)' assert_true: 'hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / .5) h w b / none)' assert_true: 'hwb(from hwb(120deg 20% 50% / .5) h w b / none)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)' assert_true: 'hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(none none none) h w b)' assert_true: 'hwb(from hwb(none none none) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(none none none / none) h w b / alpha)' assert_true: 'hwb(from hwb(none none none / none) h w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg none 50% / .5) h w b)' assert_true: 'hwb(from hwb(120deg none 50% / .5) h w b)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(120deg 20% 50% / none) h w b / alpha)' assert_true: 'hwb(from hwb(120deg 20% 50% / none) h w b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'hwb(from hwb(none 20% 50% / .5) h w b / alpha)' assert_true: 'hwb(from hwb(none 20% 50% / .5) h w b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l a b)' assert_true: 'lab(from lab(25% 20 50) l a b)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l a b / alpha)' assert_true: 'lab(from lab(25% 20 50) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a b / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(200% 300 400 / 500%) l a b / alpha)' assert_true: 'lab(from lab(200% 300 400 / 500%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(-200% -300 -400 / -500%) l a b / alpha)' assert_true: 'lab(from lab(-200% -300 -400 / -500%) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(from lab(25% 20 50) l a b) l a b)' assert_true: 'lab(from lab(from lab(25% 20 50) l a b) l a b)' is a supported value for color. expected true got false FAIL Property color value 'lab(from color(display-p3 0 0 0) l a b / alpha)' assert_true: 'lab(from color(display-p3 0 0 0) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) 0% 0 0)' assert_true: 'lab(from lab(25% 20 50) 0% 0 0)' is a supported value for color. expected true got false @@ -161,15 +226,30 @@ FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l 35 b / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l 35 b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a 35 / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a 35 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a b / .35)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a b / .35)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'lab(from lab(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'lab(from lab(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l b a)' assert_true: 'lab(from lab(25% 20 50) l b a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) l a a / a)' assert_true: 'lab(from lab(25% 20 50) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l b a)' assert_true: 'lab(from lab(25% 20 50 / 40%) l b a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a a / a)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50) calc(l) calc(a) calc(b))' assert_true: 'lab(from lab(25% 20 50) calc(l) calc(a) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' assert_true: 'lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) none none none)' assert_true: 'lab(from lab(25% 20 50) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) none none none / none)' assert_true: 'lab(from lab(25% 20 50) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) l a none)' assert_true: 'lab(from lab(25% 20 50) l a none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) l a none / alpha)' assert_true: 'lab(from lab(25% 20 50) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50) l a b / none)' assert_true: 'lab(from lab(25% 20 50) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a none / alpha)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50 / 40%) l a b / none)' assert_true: 'lab(from lab(25% 20 50 / 40%) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(none none none) l a b)' assert_true: 'lab(from lab(none none none) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(none none none / none) l a b / alpha)' assert_true: 'lab(from lab(none none none / none) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% none 50) l a b)' assert_true: 'lab(from lab(25% none 50) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'lab(from lab(25% 20 50 / none) l a b / alpha)' assert_true: 'lab(from lab(25% 20 50 / none) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l a b)' assert_true: 'oklab(from oklab(25% 20 50) l a b)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l a b / alpha)' assert_true: 'oklab(from oklab(25% 20 50) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a b / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(200% 300 400 / 500%) l a b / alpha)' assert_true: 'oklab(from oklab(200% 300 400 / 500%) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(-200% -300 -400 / -500%) l a b / alpha)' assert_true: 'oklab(from oklab(-200% -300 -400 / -500%) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(from oklab(25% 20 50) l a b) l a b)' assert_true: 'oklab(from oklab(from oklab(25% 20 50) l a b) l a b)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from color(display-p3 0 0 0) l a b / alpha)' assert_true: 'oklab(from color(display-p3 0 0 0) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) 0% 0 0)' assert_true: 'oklab(from oklab(25% 20 50) 0% 0 0)' is a supported value for color. expected true got false @@ -190,15 +270,30 @@ FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l 35 b / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l 35 b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a 35 / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a 35 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a b / .35)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a b / .35)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'oklab(from oklab(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'oklab(from oklab(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l b a)' assert_true: 'oklab(from oklab(25% 20 50) l b a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) l a a / a)' assert_true: 'oklab(from oklab(25% 20 50) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l b a)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l b a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a a / a)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a a / a)' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50) calc(l) calc(a) calc(b))' assert_true: 'oklab(from oklab(25% 20 50) calc(l) calc(a) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' assert_true: 'oklab(from oklab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) none none none)' assert_true: 'oklab(from oklab(25% 20 50) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) none none none / none)' assert_true: 'oklab(from oklab(25% 20 50) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) l a none)' assert_true: 'oklab(from oklab(25% 20 50) l a none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) l a none / alpha)' assert_true: 'oklab(from oklab(25% 20 50) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50) l a b / none)' assert_true: 'oklab(from oklab(25% 20 50) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a none / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50 / 40%) l a b / none)' assert_true: 'oklab(from oklab(25% 20 50 / 40%) l a b / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(none none none) l a b)' assert_true: 'oklab(from oklab(none none none) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(none none none / none) l a b / alpha)' assert_true: 'oklab(from oklab(none none none / none) l a b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% none 50) l a b)' assert_true: 'oklab(from oklab(25% none 50) l a b)' is a supported value for color. expected true got false +FAIL Property color value 'oklab(from oklab(25% 20 50 / none) l a b / alpha)' assert_true: 'oklab(from oklab(25% 20 50 / none) l a b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) l c h)' assert_true: 'lch(from lch(70% 45 30) l c h)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) l c h / alpha)' assert_true: 'lch(from lch(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false -FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h/ alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h/ alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(200% 300 400 / 500%) l c h / alpha)' assert_true: 'lch(from lch(200% 300 400 / 500%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(-200% -300 -400 / -500%) l c h / alpha)' assert_true: 'lch(from lch(-200% -300 -400 / -500%) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(from lch(70% 45 30) l c h) l c h)' assert_true: 'lch(from lch(from lch(70% 45 30) l c h) l c h)' is a supported value for color. expected true got false FAIL Property color value 'lch(from color(display-p3 0 0 0) l c h / alpha)' assert_true: 'lch(from color(display-p3 0 0 0) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lab(70% 45 30) l c h / alpha)' assert_true: 'lch(from lab(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false @@ -226,6 +321,10 @@ FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c 25 / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c 25 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h / .25)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h / .25)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'lch(from lch(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'lch(from lch(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) 50% 120 400deg / 500)' assert_true: 'lch(from lch(70% 45 30 / 40%) 50% 120 400deg / 500)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) 50% 120 -400deg / -500)' assert_true: 'lch(from lch(70% 45 30 / 40%) 50% 120 -400deg / -500)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) alpha c h / l)' assert_true: 'lch(from lch(70% 45 30) alpha c h / l)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) l c c / alpha)' assert_true: 'lch(from lch(70% 45 30) l c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) alpha c h / alpha)' assert_true: 'lch(from lch(70% 45 30) alpha c h / alpha)' is a supported value for color. expected true got false @@ -236,9 +335,22 @@ FAIL Property color value 'lch(from lch(70% 45 30 / 40%) alpha c c / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) alpha c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30) calc(l) calc(c) calc(h))' assert_true: 'lch(from lch(70% 45 30) calc(l) calc(c) calc(h))' is a supported value for color. expected true got false FAIL Property color value 'lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' assert_true: 'lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) none none none)' assert_true: 'lch(from lch(70% 45 30) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) none none none / none)' assert_true: 'lch(from lch(70% 45 30) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) l c none)' assert_true: 'lch(from lch(70% 45 30) l c none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) l c none / alpha)' assert_true: 'lch(from lch(70% 45 30) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30) l c h / none)' assert_true: 'lch(from lch(70% 45 30) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c none / alpha)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / 40%) l c h / none)' assert_true: 'lch(from lch(70% 45 30 / 40%) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(none none none) l c h)' assert_true: 'lch(from lch(none none none) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(none none none / none) l c h / alpha)' assert_true: 'lch(from lch(none none none / none) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% none 30) l c h)' assert_true: 'lch(from lch(70% none 30) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'lch(from lch(70% 45 30 / none) l c h / alpha)' assert_true: 'lch(from lch(70% 45 30 / none) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) l c h)' assert_true: 'oklch(from oklch(70% 45 30) l c h)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) l c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false -FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h/ alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h/ alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(200% 300 400 / 500%) l c h / alpha)' assert_true: 'oklch(from oklch(200% 300 400 / 500%) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(-200% -300 -400 / -500%) l c h / alpha)' assert_true: 'oklch(from oklch(-200% -300 -400 / -500%) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(from oklch(70% 45 30) l c h) l c h)' assert_true: 'oklch(from oklch(from oklch(70% 45 30) l c h) l c h)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from color(display-p3 0 0 0) l c h / alpha)' assert_true: 'oklch(from color(display-p3 0 0 0) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklab(70% 45 30) l c h / alpha)' assert_true: 'oklch(from oklab(70% 45 30) l c h / alpha)' is a supported value for color. expected true got false @@ -266,6 +378,10 @@ FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c 25 / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c 25 / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c 25deg / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c 25deg / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h / .25)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h / .25)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) 200% 300 400 / 500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) 200% 300 400 / 500)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) -200% -300 -400 / -500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) -200% -300 -400 / -500)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) 50% 120 400deg / 500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) 50% 120 400deg / 500)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) 50% 120 -400deg / -500)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) 50% 120 -400deg / -500)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) alpha c h / l)' assert_true: 'oklch(from oklch(70% 45 30) alpha c h / l)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) l c c / alpha)' assert_true: 'oklch(from oklch(70% 45 30) l c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) alpha c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30) alpha c h / alpha)' is a supported value for color. expected true got false @@ -276,6 +392,17 @@ FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) alpha c c / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) alpha c c / alpha)' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30) calc(l) calc(c) calc(h))' assert_true: 'oklch(from oklch(70% 45 30) calc(l) calc(c) calc(h))' is a supported value for color. expected true got false FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' assert_true: 'oklch(from oklch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) none none none)' assert_true: 'oklch(from oklch(70% 45 30) none none none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) none none none / none)' assert_true: 'oklch(from oklch(70% 45 30) none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) l c none)' assert_true: 'oklch(from oklch(70% 45 30) l c none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) l c none / alpha)' assert_true: 'oklch(from oklch(70% 45 30) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30) l c h / none)' assert_true: 'oklch(from oklch(70% 45 30) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c none / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / 40%) l c h / none)' assert_true: 'oklch(from oklch(70% 45 30 / 40%) l c h / none)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(none none none) l c h)' assert_true: 'oklch(from oklch(none none none) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(none none none / none) l c h / alpha)' assert_true: 'oklch(from oklch(none none none / none) l c h / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% none 30) l c h)' assert_true: 'oklch(from oklch(70% none 30) l c h)' is a supported value for color. expected true got false +FAIL Property color value 'oklch(from oklch(70% 45 30 / none) l c h / alpha)' assert_true: 'oklch(from oklch(70% 45 30 / none) l c h / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g b)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b)' is a supported value for color. expected true got false @@ -307,6 +434,14 @@ FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 20% / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0.2)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 20%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4 / 5)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4 / -5)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400% / 500%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400% / -500%)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb g b r)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb b alpha r / g)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r r r / r)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r r r / r)' is a supported value for color. expected true got false @@ -315,8 +450,27 @@ FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb b alpha r / g)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r r r / r)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb alpha alpha alpha / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3) srgb r g b)' assert_true: 'color(from color(srgb 1.7 1.5 1.3) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3) srgb r g b / alpha)' assert_true: 'color(from color(srgb 1.7 1.5 1.3) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b)' assert_true: 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b / alpha)' assert_true: 'color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b / alpha)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b / alpha)' assert_true: 'color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb calc(r) calc(g) calc(b))' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb none none none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb none none none / none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g none / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3) srgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g none / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / none)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb none none none) srgb r g b)' assert_true: 'color(from color(srgb none none none) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb none none none / none) srgb r g b / alpha)' assert_true: 'color(from color(srgb none none none / none) srgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 none 0.3) srgb r g b)' assert_true: 'color(from color(srgb 0.7 none 0.3) srgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb 0.7 0.5 0.3 / none) srgb r g b / alpha)' assert_true: 'color(from color(srgb 0.7 0.5 0.3 / none) srgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b)' is a supported value for color. expected true got false @@ -348,6 +502,14 @@ FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 20% / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0.2)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 20%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4 / 5)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4 / -5)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400% / 500%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400% / -500%)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear g b r)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear b alpha r / g)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r r r / r)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r r r / r)' is a supported value for color. expected true got false @@ -356,8 +518,27 @@ FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear b alpha r / g)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r r r / r)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear alpha alpha alpha / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear calc(r) calc(g) calc(b))' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none / none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g none / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / none)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear none none none) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear none none none) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear none none none / none) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear none none none / none) srgb-linear r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 none 0.3) srgb-linear r g b)' assert_true: 'color(from color(srgb-linear 0.7 none 0.3) srgb-linear r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(srgb-linear 0.7 0.5 0.3 / none) srgb-linear r g b / alpha)' assert_true: 'color(from color(srgb-linear 0.7 0.5 0.3 / none) srgb-linear r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b)' is a supported value for color. expected true got false @@ -389,6 +570,14 @@ FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 20% / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0.2)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 20%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4 / 5)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4 / -5)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400% / 500%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400% / -500%)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb g b r)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb b alpha r / g)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r r r / r)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r r r / r)' is a supported value for color. expected true got false @@ -397,8 +586,27 @@ FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb b alpha r / g)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r r r / r)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb alpha alpha alpha / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb calc(r) calc(g) calc(b))' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none / none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g none / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / none)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb none none none) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb none none none) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb none none none / none) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb none none none / none) a98-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 none 0.3) a98-rgb r g b)' assert_true: 'color(from color(a98-rgb 0.7 none 0.3) a98-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(a98-rgb 0.7 0.5 0.3 / none) a98-rgb r g b / alpha)' assert_true: 'color(from color(a98-rgb 0.7 0.5 0.3 / none) a98-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b)' is a supported value for color. expected true got false @@ -430,6 +638,14 @@ FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 20% / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0.2)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 20%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4 / 5)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4 / -5)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400% / 500%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400% / -500%)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 g b r)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 b alpha r / g)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r r r / r)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r r r / r)' is a supported value for color. expected true got false @@ -438,8 +654,27 @@ FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 b alpha r / g)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r r r / r)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 alpha alpha alpha / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 calc(r) calc(g) calc(b))' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none / none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g none / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / none)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 none none none) rec2020 r g b)' assert_true: 'color(from color(rec2020 none none none) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 none none none / none) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 none none none / none) rec2020 r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 none 0.3) rec2020 r g b)' assert_true: 'color(from color(rec2020 0.7 none 0.3) rec2020 r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(rec2020 0.7 0.5 0.3 / none) rec2020 r g b / alpha)' assert_true: 'color(from color(rec2020 0.7 0.5 0.3 / none) rec2020 r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b)' is a supported value for color. expected true got false @@ -471,6 +706,14 @@ FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 20% / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 20% / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0.2)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0.2)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 20%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 20%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4 / 5)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4 / 5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4 / -5)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4 / -5)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400% / 500%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400% / 500%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400%)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400% / -500%)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400% / -500%)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb g b r)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb g b r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb b alpha r / g)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r r r / r)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r r r / r)' is a supported value for color. expected true got false @@ -479,8 +722,27 @@ FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb b alpha r / g)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb b alpha r / g)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r r r / r)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r r r / r)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb alpha alpha alpha / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb alpha alpha alpha / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb calc(r) calc(g) calc(b))' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb calc(r) calc(g) calc(b))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb calc(r) calc(g) calc(b) / calc(alpha))' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb calc(r) calc(g) calc(b) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none / none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g none / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / none)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb none none none) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb none none none) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb none none none / none) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb none none none / none) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 none 0.3) prophoto-rgb r g b)' assert_true: 'color(from color(prophoto-rgb 0.7 none 0.3) prophoto-rgb r g b)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(prophoto-rgb 0.7 0.5 0.3 / none) prophoto-rgb r g b / alpha)' assert_true: 'color(from color(prophoto-rgb 0.7 0.5 0.3 / none) prophoto-rgb r g b / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y z)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y z)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y z / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z)' is a supported value for color. expected true got false @@ -511,6 +773,17 @@ FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x x x / x)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x x x / x)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz calc(x) calc(y) calc(z))' assert_true: 'color(from color(xyz 7 -20.5 100) xyz calc(x) calc(y) calc(z))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz calc(x) calc(y) calc(z) / calc(alpha))' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz calc(x) calc(y) calc(z) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz none none none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz none none none / none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y none / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100) xyz x y z / none)' assert_true: 'color(from color(xyz 7 -20.5 100) xyz x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y none / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / none)' assert_true: 'color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz none none none) xyz x y z)' assert_true: 'color(from color(xyz none none none) xyz x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz none none none / none) xyz x y z / alpha)' assert_true: 'color(from color(xyz none none none / none) xyz x y z / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 none 100) xyz x y z)' assert_true: 'color(from color(xyz 7 none 100) xyz x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz 7 -20.5 100 / none) xyz x y z / alpha)' assert_true: 'color(from color(xyz 7 -20.5 100 / none) xyz x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z)' is a supported value for color. expected true got false @@ -541,6 +814,17 @@ FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x x x / x)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x x x / x)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 calc(x) calc(y) calc(z))' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 calc(x) calc(y) calc(z))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 calc(x) calc(y) calc(z) / calc(alpha))' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 calc(x) calc(y) calc(z) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none / none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y none / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / none)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 none none none) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 none none none) xyz-d50 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 none none none / none) xyz-d50 x y z / alpha)' assert_true: 'color(from color(xyz-d50 none none none / none) xyz-d50 x y z / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 none 100) xyz-d50 x y z)' assert_true: 'color(from color(xyz-d50 7 none 100) xyz-d50 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d50 7 -20.5 100 / none) xyz-d50 x y z / alpha)' assert_true: 'color(from color(xyz-d50 7 -20.5 100 / none) xyz-d50 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z)' is a supported value for color. expected true got false @@ -571,6 +855,17 @@ FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x x x / x)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x x x / x)' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 calc(x) calc(y) calc(z))' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 calc(x) calc(y) calc(z))' is a supported value for color. expected true got false FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 calc(x) calc(y) calc(z) / calc(alpha))' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 calc(x) calc(y) calc(z) / calc(alpha))' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none / none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y none / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y none / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / none)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / none)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 none none none) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 none none none) xyz-d65 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)' assert_true: 'color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 none 100) xyz-d65 x y z)' assert_true: 'color(from color(xyz-d65 7 none 100) xyz-d65 x y z)' is a supported value for color. expected true got false +FAIL Property color value 'color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)' assert_true: 'color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)' is a supported value for color. expected true got false FAIL Property color value 'rgb(from var(--bg-color) r g b / 80%)' assert_equals: expected "rgba(0, 0, 255, 0.8)" but got "rgb(0, 0, 0)" FAIL Property color value 'lch(from var(--color) calc(l / 2) c h)' assert_equals: expected "lch(23.138971% 67.989716 134.39125)" but got "rgb(0, 0, 0)" FAIL Property color value 'rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))' assert_equals: expected "rgb(76, 76, 76)" but got "rgb(0, 0, 0)"
diff --git a/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-valid-expected.txt b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-valid-expected.txt new file mode 100644 index 0000000..612ee9b --- /dev/null +++ b/third_party/blink/web_tests/flag-specific/disable-layout-ng/virtual/system-color-compute/external/wpt/css/css-color/parsing/relative-color-valid-expected.txt
@@ -0,0 +1,885 @@ +This is a testharness.js-based test. +Found 881 tests; 13 PASS, 868 FAIL, 0 TIMEOUT, 0 NOTRUN. +FAIL e.style['color'] = "rgb(from rebeccapurple r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from hsl(120deg 20% 50% / .5) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(from rebeccapurple r g b) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from color(display-p3 0 1 0) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lab(100% 104.3 -50.9) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lab(0% 104.3 -50.9) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lch(100% 116 334) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from lch(0% 116 334) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklab(100% 0.365 -0.16) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklab(0% 0.365 -0.16) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklch(100% 0.399 336.3) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from oklch(0% 0.399 336.3) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 25 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 25 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g b / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / .20)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 25 g b / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 25 b / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g 25 / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 25 g b / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 25 b / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r g 25 / 25%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 20% 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r 10 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple 0% 10 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 20% 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) r 10 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) 0% 10 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r calc(g * 2) 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple b calc(r * .5) 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r calc(g * .5 + g * .5) 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r calc(b * .5 - g * .5) 10)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20%, 40%, 60%, 80%) calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rebeccapurple r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% 40% 60% / 80%) r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% 40% 60% / 80%) r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(none none none) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(none none none / none) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% none 60%) r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "rgb(from rgb(20% 40% 60% / none) r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(from rebeccapurple h s l) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from color(display-p3 0 1 0) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lab(100% 104.3 -50.9) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lab(0% 104.3 -50.9) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lch(100% 116 334) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from lch(0% 116 334) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklab(100% 0.365 -0.16) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklab(0% 0.365 -0.16) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklch(100% 0.399 336.3) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from oklch(0% 0.399 336.3) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0deg 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0deg 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0 s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 0deg s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h 0% l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s 0% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s l / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 0 s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 0deg s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h 0% l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s 0% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s l / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 25 s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple 25deg s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h 20% l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s l / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 25 s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) 25deg s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h 20% l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h s l / .2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h l s)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h alpha l / s)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h l l / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h l s)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h alpha l / s)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h l l / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple calc(h) calc(s) calc(l))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rgb(20%, 40%, 60%, 80%) calc(h) calc(s) calc(l) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple h s l / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from rebeccapurple none s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) h s l / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / .5) none s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(none none none) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(none none none / none) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg none 50% / .5) h s l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(120deg 20% 50% / none) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hsl(from hsl(none 20% 50% / .5) h s l / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hsl(120deg 20% 50% / .5) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(from rebeccapurple h w b) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from color(display-p3 0 1 0) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lab(100% 104.3 -50.9) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lab(0% 104.3 -50.9) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lch(100% 116 334) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from lch(0% 116 334) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklab(100% 0.365 -0.16) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklab(0% 0.365 -0.16) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklch(100% 0.399 336.3) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from oklch(0% 0.399 336.3) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0deg 0% 0%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0deg 0% 0% / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0 w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 0deg w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h 0% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w 0% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 0 w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 0deg w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h 0% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w 0% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 25 w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple 25deg w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w b / .2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 25 w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) 25deg w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w b / .2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h b w)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h alpha w / b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w w / w)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h b w)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h alpha w / b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h w w / w)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) h alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple calc(h) calc(w) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rgb(20%, 40%, 60%, 80%) calc(h) calc(w) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple h w b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from rebeccapurple none w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) h w none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) h w b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / .5) none w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(none none none) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(none none none / none) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg none 50% / .5) h w b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(120deg 20% 50% / none) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "hwb(from hwb(none 20% 50% / .5) h w b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(200% 300 400 / 500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(-200% -300 -400 / -500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(from lab(25% 20 50) l a b) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from color(display-p3 0 0 0) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) 0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) 0% 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) 0% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) 0% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) 35% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l 35 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a 35 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b / .35)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) 35% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l 35 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a 35 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a b / .35)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) calc(l) calc(a) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / 40%) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(none none none) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(none none none / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% none 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lab(from lab(25% 20 50 / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(200% 300 400 / 500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(-200% -300 -400 / -500%) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(from oklab(25% 20 50) l a b) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from color(display-p3 0 0 0) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) 0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) 0% 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) 0% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) 0% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) 35% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l 35 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a 35 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b / .35)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) 35% a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l 35 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a 35 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a b / .35)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l b a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a a / a)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) calc(l) calc(a) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) calc(l) calc(a) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / 40%) l a b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(none none none) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(none none none / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% none 50) l a b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklab(from oklab(25% 20 50 / none) l a b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(200% 300 400 / 500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(-200% -300 -400 / -500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(from lch(70% 45 30) l c h) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from color(display-p3 0 0 0) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lab(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 0% 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 0% 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 0% 0 0deg / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 0% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l 0 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c 0deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 0% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l 0 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c 0deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) 25% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l 25 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c 25deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 25% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l 25 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c 25deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 50% 120 400deg / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) 50% 120 -400deg / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) alpha c h / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) alpha c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) alpha c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) alpha c h / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) alpha c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) alpha c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) calc(l) calc(c) calc(h))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / 40%) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(none none none) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(none none none / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% none 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "lch(from lch(70% 45 30 / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(200% 300 400 / 500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(-200% -300 -400 / -500%) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(from oklch(70% 45 30) l c h) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from color(display-p3 0 0 0) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklab(70% 45 30) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 0% 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 0% 0 0deg)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 0% 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 0% 0 0deg / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 0% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l 0 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c 0deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 0% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l 0 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c 0deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) 25% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l 25 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c 25deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 25% c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l 25 h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c 25 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c 25deg / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h / .25)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 200% 300 400 / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) -200% -300 -400 / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 50% 120 400deg / 500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) 50% 120 -400deg / -500)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) alpha c h / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) alpha c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) alpha c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) alpha c h / l)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) alpha c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) alpha c c / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) calc(l) calc(c) calc(h))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) calc(l) calc(c) calc(h) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / 40%) l c h / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(none none none) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(none none none / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% none 30) l c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "oklch(from oklch(70% 45 30 / none) l c h / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(srgb 0.7 0.5 0.3) srgb r g b) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 1.7 1.5 1.3 / 140%) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb -0.7 -0.5 -0.3 / -40%) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3) srgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / 40%) srgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb none none none) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb none none none / none) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 none 0.3) srgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb 0.7 0.5 0.3 / none) srgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 1.7 1.5 1.3 / 140%) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear -0.7 -0.5 -0.3 / -40%) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3) srgb-linear r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / 40%) srgb-linear r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear none none none) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear none none none / none) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 none 0.3) srgb-linear r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(srgb-linear 0.7 0.5 0.3 / none) srgb-linear r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 1.7 1.5 1.3 / 140%) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb -0.7 -0.5 -0.3 / -40%) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3) a98-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / 40%) a98-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb none none none) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb none none none / none) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 none 0.3) a98-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(a98-rgb 0.7 0.5 0.3 / none) a98-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 1.7 1.5 1.3 / 140%) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 -0.7 -0.5 -0.3 / -40%) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3) rec2020 r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / 40%) rec2020 r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 none none none) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 none none none / none) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 none 0.3) rec2020 r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(rec2020 0.7 0.5 0.3 / none) rec2020 r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb 0 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r 0 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb 0.2 g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb 20% g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r 0.2 b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r 20% b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g 20% / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 2 3 4 / 5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -2 -3 -4 / -5)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb 200% 300% 400% / 500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb -200% -300% -400% / -500%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb g b r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb b alpha r / g)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r r r / r)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb alpha alpha alpha / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 1.7 1.5 1.3 / 140%) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb -0.7 -0.5 -0.3 / -40%) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb calc(r) calc(g) calc(b))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb calc(r) calc(g) calc(b) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3) prophoto-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / 40%) prophoto-rgb r g b / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb none none none) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb none none none / none) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 none 0.3) prophoto-rgb r g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(prophoto-rgb 0.7 0.5 0.3 / none) prophoto-rgb r g b / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(xyz 7 -20.5 100) xyz x y z) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz calc(x) calc(y) calc(z))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz calc(x) calc(y) calc(z) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100) xyz x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / 40%) xyz x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz none none none) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz none none none / none) xyz x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 none 100) xyz x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz 7 -20.5 100 / none) xyz x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 calc(x) calc(y) calc(z))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 calc(x) calc(y) calc(z) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100) xyz-d50 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / 40%) xyz-d50 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 none none none) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 none none none / none) xyz-d50 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 none 100) xyz-d50 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d50 7 -20.5 100 / none) xyz-d50 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0 0 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0 0 0 / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 0 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x 0 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y 0 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / 0)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / 20%)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 0.2 y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x 0.2 z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y 0.2 / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / 0.2)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 y z x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x x x / x)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 calc(x) calc(y) calc(z))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 calc(x) calc(y) calc(z) / calc(alpha))" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 none none none / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100) xyz-d65 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y none / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / 40%) xyz-d65 x y z / none)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 none none none) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 none none none / none) xyz-d65 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 none 100) xyz-d65 x y z)" should set the property value assert_not_equals: property should be set got disallowed value "" +FAIL e.style['color'] = "color(from color(xyz-d65 7 -20.5 100 / none) xyz-d65 x y z / alpha)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "rgb(from var(--bg-color) r g b / 80%)" should set the property value +PASS e.style['color'] = "lch(from var(--color) calc(l / 2) c h)" should set the property value +PASS e.style['color'] = "rgb(from var(--color) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11) calc(r * .3 + g * .59 + b * .11))" should set the property value +PASS e.style['color'] = "lch(from var(--color) l 0 h)" should set the property value +FAIL e.style['color'] = "rgb(from indianred 255 g b)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "hsl(from var(--accent) calc(h + 180deg) s l)" should set the property value +PASS e.style['color'] = "lab(from var(--mycolor) l a b / 100%)" should set the property value +PASS e.style['color'] = "lab(from var(--mycolor) l a b / calc(alpha * 0.8))" should set the property value +PASS e.style['color'] = "lab(from var(--mycolor) l a b / calc(alpha - 20%))" should set the property value +PASS e.style['color'] = "lab(from var(--mycolor) l 0 0)" should set the property value +FAIL e.style['color'] = "lch(from peru calc(l * 0.8) c h)" should set the property value assert_not_equals: property should be set got disallowed value "" +PASS e.style['color'] = "LCH(from var(--accent) l c calc(h + 180deg))" should set the property value +PASS e.style['color'] = "lch(from var(--mycolor) l 0 h)" should set the property value +PASS e.style['color'] = "var(--mygray)" should set the property value +PASS e.style['color'] = "lch(from var(--mygray) l 30 h)" should set the property value +Harness: the test ran to completion. +
diff --git a/third_party/blink/web_tests/http/tests/websocket/slow-tcp-close.html b/third_party/blink/web_tests/http/tests/websocket/slow-tcp-close.html new file mode 100644 index 0000000..6271898 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/websocket/slow-tcp-close.html
@@ -0,0 +1,24 @@ +<!DOCTYPE html> + +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> + +<script> +async_test(t => { + const ws = new WebSocket('ws://127.0.0.1:8880/slow-tcp-close'); + let start; + ws.onopen = t.step_func(() => { + ws.close(); + start = performance.now(); + }); + ws.onclose = t.step_func_done(evt => { + const elapsed = performance.now() - start; + // Chromium closes the connection after waiting 2 seconds. This is not + // standardised. + assert_less_than(elapsed, 3000, 'browser should have closed connection'); + + // TODO(ricea): Change this to true to align with other browsers. + assert_false(evt.wasClean, 'wasClean should be correct'); + }); +}, 'verify that the browser closes TCP connections when the server is slow'); +</script>
diff --git a/third_party/blink/web_tests/http/tests/websocket/slow-tcp-close_wsh.py b/third_party/blink/web_tests/http/tests/websocket/slow-tcp-close_wsh.py new file mode 100644 index 0000000..ffb090bc --- /dev/null +++ b/third_party/blink/web_tests/http/tests/websocket/slow-tcp-close_wsh.py
@@ -0,0 +1,25 @@ +import time +from mod_pywebsocket import handshake +from mod_pywebsocket import stream + + +def web_socket_do_extra_handshake(request): + pass + + +def web_socket_transfer_data(request): + while request.ws_stream.receive_message() is not None: + pass + + +def web_socket_passive_closing_handshake(request): + # Send a close frame. + request.connection.write(stream.create_close_frame(b'')) + + # Chromium will wait 2 seconds for the server to close the connection before + # giving up and closing it itself. Add an extra second to avoid the test + # being flaky. + time.sleep(3) + + # Prevent pywebsocket from sending another close frame. + raise handshake.AbortedByUserException('Abort the connection')
diff --git a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/plz-dedicated-worker/external/wpt/referrer-policy/gen/srcdoc.meta/strict-origin/iframe-tag.http-expected.txt b/third_party/blink/web_tests/platform/mac-mac10.13/virtual/plz-dedicated-worker/external/wpt/referrer-policy/gen/srcdoc.meta/strict-origin/iframe-tag.http-expected.txt deleted file mode 100644 index 04a9370..0000000 --- a/third_party/blink/web_tests/platform/mac-mac10.13/virtual/plz-dedicated-worker/external/wpt/referrer-policy/gen/srcdoc.meta/strict-origin/iframe-tag.http-expected.txt +++ /dev/null
@@ -1,15 +0,0 @@ -This is a testharness.js-based test. -PASS Referrer Policy: Expects origin for iframe-tag to cross-http origin and keep-origin redirection from http context. -PASS Referrer Policy: Expects origin for iframe-tag to cross-http origin and no-redirect redirection from http context. -PASS Referrer Policy: Expects origin for iframe-tag to cross-http origin and swap-origin redirection from http context. -PASS Referrer Policy: Expects origin for iframe-tag to cross-https origin and keep-origin redirection from http context. -PASS Referrer Policy: Expects origin for iframe-tag to cross-https origin and no-redirect redirection from http context. -PASS Referrer Policy: Expects origin for iframe-tag to cross-https origin and swap-origin redirection from http context. -PASS Referrer Policy: Expects origin for iframe-tag to same-http origin and keep-origin redirection from http context. -PASS Referrer Policy: Expects origin for iframe-tag to same-http origin and no-redirect redirection from http context. -PASS Referrer Policy: Expects origin for iframe-tag to same-http origin and swap-origin redirection from http context. -PASS Referrer Policy: Expects origin for iframe-tag to same-https origin and keep-origin redirection from http context. -PASS Referrer Policy: Expects origin for iframe-tag to same-https origin and no-redirect redirection from http context. -FAIL Referrer Policy: Expects origin for iframe-tag to same-https origin and swap-origin redirection from http context. assert_in_array: document.referrer value "http://web-platform.test:8001/referrer-policy/gen/srcdoc.meta/strict-origin/iframe-tag.http.html" not in array ["http://web-platform.test:8001/", undefined] -Harness: the test ran to completion. -
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/OWNERS b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/OWNERS new file mode 100644 index 0000000..d0b8610 --- /dev/null +++ b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/OWNERS
@@ -0,0 +1,5 @@ +set noparent + +# Web-exposed API changes may require approval from blink API OWNERS. +# See http://www.chromium.org/blink#new-features for details. +file://third_party/blink/API_OWNERS
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/README.txt b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/README.txt new file mode 100644 index 0000000..fb69fbf --- /dev/null +++ b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/README.txt
@@ -0,0 +1,3 @@ +These files override the expected lists of public methods for the stable +channel of Chrome. See web_tests/http/tests/worklet/webexposed/ for +details.
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt new file mode 100644 index 0000000..60dc81f --- /dev/null +++ b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-audio-worklet-expected.txt
@@ -0,0 +1,161 @@ +CONSOLE MESSAGE: This test logs exposed APIs from AudioWorkletGlobalScope +CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface AudioWorkletGlobalScope : WorkletGlobalScope +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface AudioWorkletProcessor +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter port +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface ByteLengthQueuingStrategy +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter highWaterMark +CONSOLE MESSAGE: getter size +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CountQueuingStrategy +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter highWaterMark +CONSOLE MESSAGE: getter size +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface Event +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: attribute AT_TARGET +CONSOLE MESSAGE: attribute BUBBLING_PHASE +CONSOLE MESSAGE: attribute CAPTURING_PHASE +CONSOLE MESSAGE: attribute NONE +CONSOLE MESSAGE: getter bubbles +CONSOLE MESSAGE: getter cancelBubble +CONSOLE MESSAGE: getter cancelable +CONSOLE MESSAGE: getter composed +CONSOLE MESSAGE: getter currentTarget +CONSOLE MESSAGE: getter defaultPrevented +CONSOLE MESSAGE: getter eventPhase +CONSOLE MESSAGE: getter path +CONSOLE MESSAGE: getter returnValue +CONSOLE MESSAGE: getter srcElement +CONSOLE MESSAGE: getter target +CONSOLE MESSAGE: getter timeStamp +CONSOLE MESSAGE: getter type +CONSOLE MESSAGE: method composedPath +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method initEvent +CONSOLE MESSAGE: method preventDefault +CONSOLE MESSAGE: method stopImmediatePropagation +CONSOLE MESSAGE: method stopPropagation +CONSOLE MESSAGE: setter cancelBubble +CONSOLE MESSAGE: setter returnValue +CONSOLE MESSAGE: interface EventTarget +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method addEventListener +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method dispatchEvent +CONSOLE MESSAGE: method removeEventListener +CONSOLE MESSAGE: interface MessageEvent : Event +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter data +CONSOLE MESSAGE: getter lastEventId +CONSOLE MESSAGE: getter origin +CONSOLE MESSAGE: getter ports +CONSOLE MESSAGE: getter source +CONSOLE MESSAGE: getter userActivation +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method initMessageEvent +CONSOLE MESSAGE: interface MessagePort : EventTarget +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter onmessage +CONSOLE MESSAGE: getter onmessageerror +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method postMessage +CONSOLE MESSAGE: method start +CONSOLE MESSAGE: setter onmessage +CONSOLE MESSAGE: setter onmessageerror +CONSOLE MESSAGE: interface ReadableByteStreamController +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter byobRequest +CONSOLE MESSAGE: getter desiredSize +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method enqueue +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: interface ReadableStream +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter locked +CONSOLE MESSAGE: method cancel +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method getReader +CONSOLE MESSAGE: method pipeThrough +CONSOLE MESSAGE: method pipeTo +CONSOLE MESSAGE: method tee +CONSOLE MESSAGE: interface ReadableStreamBYOBReader +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter closed +CONSOLE MESSAGE: method cancel +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method read +CONSOLE MESSAGE: method releaseLock +CONSOLE MESSAGE: interface ReadableStreamBYOBRequest +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter view +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method respond +CONSOLE MESSAGE: method respondWithNewView +CONSOLE MESSAGE: interface ReadableStreamDefaultController +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter desiredSize +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method enqueue +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: interface ReadableStreamDefaultReader +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter closed +CONSOLE MESSAGE: method cancel +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method read +CONSOLE MESSAGE: method releaseLock +CONSOLE MESSAGE: interface TransformStream +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter readable +CONSOLE MESSAGE: getter writable +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface UserActivation +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter hasBeenActive +CONSOLE MESSAGE: getter isActive +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface WorkletGlobalScope +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface WritableStream +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter locked +CONSOLE MESSAGE: method abort +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method getWriter +CONSOLE MESSAGE: interface WritableStreamDefaultController +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter signal +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: interface WritableStreamDefaultWriter +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter closed +CONSOLE MESSAGE: getter desiredSize +CONSOLE MESSAGE: getter ready +CONSOLE MESSAGE: method abort +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method releaseLock +CONSOLE MESSAGE: method write +CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: [GLOBAL OBJECT] +CONSOLE MESSAGE: attribute console +CONSOLE MESSAGE: attribute globalThis +CONSOLE MESSAGE: getter currentFrame +CONSOLE MESSAGE: getter currentTime +CONSOLE MESSAGE: getter sampleRate +CONSOLE MESSAGE: method gc +CONSOLE MESSAGE: method registerProcessor +
diff --git a/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt new file mode 100644 index 0000000..79375fc --- /dev/null +++ b/third_party/blink/web_tests/virtual/stable/http/tests/worklet/webexposed/global-interface-listing-paint-worklet-expected.txt
@@ -0,0 +1,738 @@ +CONSOLE MESSAGE: This test logs exposed APIs once from each PaintWorkletGlobalScope +CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface ByteLengthQueuingStrategy +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter highWaterMark +CONSOLE MESSAGE: getter size +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSImageValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSKeywordValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter value +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter value +CONSOLE MESSAGE: interface CSSMathClamp : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter lower +CONSOLE MESSAGE: getter upper +CONSOLE MESSAGE: getter value +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathInvert : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter value +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathMax : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter values +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathMin : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter values +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathNegate : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter value +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathProduct : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter values +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathSum : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter values +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathValue : CSSNumericValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter operator +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMatrixComponent : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter matrix +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter matrix +CONSOLE MESSAGE: interface CSSNumericArray +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter length +CONSOLE MESSAGE: method @@iterator +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method entries +CONSOLE MESSAGE: method forEach +CONSOLE MESSAGE: method keys +CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface CSSNumericValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method add +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method div +CONSOLE MESSAGE: method equals +CONSOLE MESSAGE: method max +CONSOLE MESSAGE: method min +CONSOLE MESSAGE: method mul +CONSOLE MESSAGE: method sub +CONSOLE MESSAGE: method to +CONSOLE MESSAGE: method toSum +CONSOLE MESSAGE: method type +CONSOLE MESSAGE: interface CSSPerspective : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter length +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter length +CONSOLE MESSAGE: interface CSSPositionValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter x +CONSOLE MESSAGE: getter y +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter x +CONSOLE MESSAGE: setter y +CONSOLE MESSAGE: interface CSSRotate : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter angle +CONSOLE MESSAGE: getter x +CONSOLE MESSAGE: getter y +CONSOLE MESSAGE: getter z +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter angle +CONSOLE MESSAGE: setter x +CONSOLE MESSAGE: setter y +CONSOLE MESSAGE: setter z +CONSOLE MESSAGE: interface CSSScale : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter x +CONSOLE MESSAGE: getter y +CONSOLE MESSAGE: getter z +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter x +CONSOLE MESSAGE: setter y +CONSOLE MESSAGE: setter z +CONSOLE MESSAGE: interface CSSSkew : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter ax +CONSOLE MESSAGE: getter ay +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter ax +CONSOLE MESSAGE: setter ay +CONSOLE MESSAGE: interface CSSSkewX : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter ax +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter ax +CONSOLE MESSAGE: interface CSSSkewY : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter ay +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter ay +CONSOLE MESSAGE: interface CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method toString +CONSOLE MESSAGE: interface CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter is2D +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method toMatrix +CONSOLE MESSAGE: method toString +CONSOLE MESSAGE: setter is2D +CONSOLE MESSAGE: interface CSSTransformValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter is2D +CONSOLE MESSAGE: getter length +CONSOLE MESSAGE: method @@iterator +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method entries +CONSOLE MESSAGE: method forEach +CONSOLE MESSAGE: method keys +CONSOLE MESSAGE: method toMatrix +CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface CSSTranslate : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter x +CONSOLE MESSAGE: getter y +CONSOLE MESSAGE: getter z +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter x +CONSOLE MESSAGE: setter y +CONSOLE MESSAGE: setter z +CONSOLE MESSAGE: interface CSSUnitValue : CSSNumericValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter unit +CONSOLE MESSAGE: getter value +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter value +CONSOLE MESSAGE: interface CSSUnparsedValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter length +CONSOLE MESSAGE: method @@iterator +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method entries +CONSOLE MESSAGE: method forEach +CONSOLE MESSAGE: method keys +CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface CSSVariableReferenceValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter fallback +CONSOLE MESSAGE: getter variable +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter variable +CONSOLE MESSAGE: interface CanvasFilter +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CountQueuingStrategy +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter highWaterMark +CONSOLE MESSAGE: getter size +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface PaintRenderingContext2D +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter fillStyle +CONSOLE MESSAGE: getter filter +CONSOLE MESSAGE: getter globalAlpha +CONSOLE MESSAGE: getter globalCompositeOperation +CONSOLE MESSAGE: getter imageSmoothingEnabled +CONSOLE MESSAGE: getter lineCap +CONSOLE MESSAGE: getter lineDashOffset +CONSOLE MESSAGE: getter lineJoin +CONSOLE MESSAGE: getter lineWidth +CONSOLE MESSAGE: getter miterLimit +CONSOLE MESSAGE: getter shadowBlur +CONSOLE MESSAGE: getter shadowColor +CONSOLE MESSAGE: getter shadowOffsetX +CONSOLE MESSAGE: getter shadowOffsetY +CONSOLE MESSAGE: getter strokeStyle +CONSOLE MESSAGE: method arc +CONSOLE MESSAGE: method arcTo +CONSOLE MESSAGE: method beginPath +CONSOLE MESSAGE: method bezierCurveTo +CONSOLE MESSAGE: method clearRect +CONSOLE MESSAGE: method clip +CONSOLE MESSAGE: method closePath +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method createConicGradient +CONSOLE MESSAGE: method createLinearGradient +CONSOLE MESSAGE: method createPattern +CONSOLE MESSAGE: method createRadialGradient +CONSOLE MESSAGE: method drawImage +CONSOLE MESSAGE: method ellipse +CONSOLE MESSAGE: method fill +CONSOLE MESSAGE: method fillRect +CONSOLE MESSAGE: method getLineDash +CONSOLE MESSAGE: method getTransform +CONSOLE MESSAGE: method isPointInPath +CONSOLE MESSAGE: method isPointInStroke +CONSOLE MESSAGE: method lineTo +CONSOLE MESSAGE: method moveTo +CONSOLE MESSAGE: method quadraticCurveTo +CONSOLE MESSAGE: method rect +CONSOLE MESSAGE: method reset +CONSOLE MESSAGE: method resetTransform +CONSOLE MESSAGE: method restore +CONSOLE MESSAGE: method rotate +CONSOLE MESSAGE: method roundRect +CONSOLE MESSAGE: method save +CONSOLE MESSAGE: method scale +CONSOLE MESSAGE: method setLineDash +CONSOLE MESSAGE: method setTransform +CONSOLE MESSAGE: method stroke +CONSOLE MESSAGE: method strokeRect +CONSOLE MESSAGE: method transform +CONSOLE MESSAGE: method translate +CONSOLE MESSAGE: setter fillStyle +CONSOLE MESSAGE: setter filter +CONSOLE MESSAGE: setter globalAlpha +CONSOLE MESSAGE: setter globalCompositeOperation +CONSOLE MESSAGE: setter imageSmoothingEnabled +CONSOLE MESSAGE: setter lineCap +CONSOLE MESSAGE: setter lineDashOffset +CONSOLE MESSAGE: setter lineJoin +CONSOLE MESSAGE: setter lineWidth +CONSOLE MESSAGE: setter miterLimit +CONSOLE MESSAGE: setter shadowBlur +CONSOLE MESSAGE: setter shadowColor +CONSOLE MESSAGE: setter shadowOffsetX +CONSOLE MESSAGE: setter shadowOffsetY +CONSOLE MESSAGE: setter strokeStyle +CONSOLE MESSAGE: interface PaintSize +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter height +CONSOLE MESSAGE: getter width +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface PaintWorkletGlobalScope : WorkletGlobalScope +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface Path2D +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method addPath +CONSOLE MESSAGE: method arc +CONSOLE MESSAGE: method arcTo +CONSOLE MESSAGE: method bezierCurveTo +CONSOLE MESSAGE: method closePath +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method ellipse +CONSOLE MESSAGE: method lineTo +CONSOLE MESSAGE: method moveTo +CONSOLE MESSAGE: method quadraticCurveTo +CONSOLE MESSAGE: method rect +CONSOLE MESSAGE: method roundRect +CONSOLE MESSAGE: interface ReadableByteStreamController +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter byobRequest +CONSOLE MESSAGE: getter desiredSize +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method enqueue +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: interface ReadableStream +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter locked +CONSOLE MESSAGE: method cancel +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method getReader +CONSOLE MESSAGE: method pipeThrough +CONSOLE MESSAGE: method pipeTo +CONSOLE MESSAGE: method tee +CONSOLE MESSAGE: interface ReadableStreamBYOBReader +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter closed +CONSOLE MESSAGE: method cancel +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method read +CONSOLE MESSAGE: method releaseLock +CONSOLE MESSAGE: interface ReadableStreamBYOBRequest +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter view +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method respond +CONSOLE MESSAGE: method respondWithNewView +CONSOLE MESSAGE: interface ReadableStreamDefaultController +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter desiredSize +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method enqueue +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: interface ReadableStreamDefaultReader +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter closed +CONSOLE MESSAGE: method cancel +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method read +CONSOLE MESSAGE: method releaseLock +CONSOLE MESSAGE: interface StylePropertyMapReadOnly +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter size +CONSOLE MESSAGE: method @@iterator +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method entries +CONSOLE MESSAGE: method forEach +CONSOLE MESSAGE: method get +CONSOLE MESSAGE: method getAll +CONSOLE MESSAGE: method has +CONSOLE MESSAGE: method keys +CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface TransformStream +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter readable +CONSOLE MESSAGE: getter writable +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface WorkletGlobalScope +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface WritableStream +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter locked +CONSOLE MESSAGE: method abort +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method getWriter +CONSOLE MESSAGE: interface WritableStreamDefaultController +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter signal +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: interface WritableStreamDefaultWriter +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter closed +CONSOLE MESSAGE: getter desiredSize +CONSOLE MESSAGE: getter ready +CONSOLE MESSAGE: method abort +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method releaseLock +CONSOLE MESSAGE: method write +CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: [GLOBAL OBJECT] +CONSOLE MESSAGE: attribute console +CONSOLE MESSAGE: attribute globalThis +CONSOLE MESSAGE: getter devicePixelRatio +CONSOLE MESSAGE: method gc +CONSOLE MESSAGE: method registerPaint +CONSOLE MESSAGE: [INTERFACES] +CONSOLE MESSAGE: interface ByteLengthQueuingStrategy +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter highWaterMark +CONSOLE MESSAGE: getter size +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSImageValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSKeywordValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter value +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter value +CONSOLE MESSAGE: interface CSSMathClamp : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter lower +CONSOLE MESSAGE: getter upper +CONSOLE MESSAGE: getter value +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathInvert : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter value +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathMax : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter values +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathMin : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter values +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathNegate : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter value +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathProduct : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter values +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathSum : CSSMathValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter values +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMathValue : CSSNumericValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter operator +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CSSMatrixComponent : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter matrix +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter matrix +CONSOLE MESSAGE: interface CSSNumericArray +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter length +CONSOLE MESSAGE: method @@iterator +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method entries +CONSOLE MESSAGE: method forEach +CONSOLE MESSAGE: method keys +CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface CSSNumericValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method add +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method div +CONSOLE MESSAGE: method equals +CONSOLE MESSAGE: method max +CONSOLE MESSAGE: method min +CONSOLE MESSAGE: method mul +CONSOLE MESSAGE: method sub +CONSOLE MESSAGE: method to +CONSOLE MESSAGE: method toSum +CONSOLE MESSAGE: method type +CONSOLE MESSAGE: interface CSSPerspective : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter length +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter length +CONSOLE MESSAGE: interface CSSPositionValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter x +CONSOLE MESSAGE: getter y +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter x +CONSOLE MESSAGE: setter y +CONSOLE MESSAGE: interface CSSRotate : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter angle +CONSOLE MESSAGE: getter x +CONSOLE MESSAGE: getter y +CONSOLE MESSAGE: getter z +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter angle +CONSOLE MESSAGE: setter x +CONSOLE MESSAGE: setter y +CONSOLE MESSAGE: setter z +CONSOLE MESSAGE: interface CSSScale : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter x +CONSOLE MESSAGE: getter y +CONSOLE MESSAGE: getter z +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter x +CONSOLE MESSAGE: setter y +CONSOLE MESSAGE: setter z +CONSOLE MESSAGE: interface CSSSkew : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter ax +CONSOLE MESSAGE: getter ay +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter ax +CONSOLE MESSAGE: setter ay +CONSOLE MESSAGE: interface CSSSkewX : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter ax +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter ax +CONSOLE MESSAGE: interface CSSSkewY : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter ay +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter ay +CONSOLE MESSAGE: interface CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method toString +CONSOLE MESSAGE: interface CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter is2D +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method toMatrix +CONSOLE MESSAGE: method toString +CONSOLE MESSAGE: setter is2D +CONSOLE MESSAGE: interface CSSTransformValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter is2D +CONSOLE MESSAGE: getter length +CONSOLE MESSAGE: method @@iterator +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method entries +CONSOLE MESSAGE: method forEach +CONSOLE MESSAGE: method keys +CONSOLE MESSAGE: method toMatrix +CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface CSSTranslate : CSSTransformComponent +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter x +CONSOLE MESSAGE: getter y +CONSOLE MESSAGE: getter z +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter x +CONSOLE MESSAGE: setter y +CONSOLE MESSAGE: setter z +CONSOLE MESSAGE: interface CSSUnitValue : CSSNumericValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter unit +CONSOLE MESSAGE: getter value +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter value +CONSOLE MESSAGE: interface CSSUnparsedValue : CSSStyleValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter length +CONSOLE MESSAGE: method @@iterator +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method entries +CONSOLE MESSAGE: method forEach +CONSOLE MESSAGE: method keys +CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface CSSVariableReferenceValue +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter fallback +CONSOLE MESSAGE: getter variable +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: setter variable +CONSOLE MESSAGE: interface CanvasFilter +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface CountQueuingStrategy +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter highWaterMark +CONSOLE MESSAGE: getter size +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface PaintRenderingContext2D +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter fillStyle +CONSOLE MESSAGE: getter filter +CONSOLE MESSAGE: getter globalAlpha +CONSOLE MESSAGE: getter globalCompositeOperation +CONSOLE MESSAGE: getter imageSmoothingEnabled +CONSOLE MESSAGE: getter lineCap +CONSOLE MESSAGE: getter lineDashOffset +CONSOLE MESSAGE: getter lineJoin +CONSOLE MESSAGE: getter lineWidth +CONSOLE MESSAGE: getter miterLimit +CONSOLE MESSAGE: getter shadowBlur +CONSOLE MESSAGE: getter shadowColor +CONSOLE MESSAGE: getter shadowOffsetX +CONSOLE MESSAGE: getter shadowOffsetY +CONSOLE MESSAGE: getter strokeStyle +CONSOLE MESSAGE: method arc +CONSOLE MESSAGE: method arcTo +CONSOLE MESSAGE: method beginPath +CONSOLE MESSAGE: method bezierCurveTo +CONSOLE MESSAGE: method clearRect +CONSOLE MESSAGE: method clip +CONSOLE MESSAGE: method closePath +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method createConicGradient +CONSOLE MESSAGE: method createLinearGradient +CONSOLE MESSAGE: method createPattern +CONSOLE MESSAGE: method createRadialGradient +CONSOLE MESSAGE: method drawImage +CONSOLE MESSAGE: method ellipse +CONSOLE MESSAGE: method fill +CONSOLE MESSAGE: method fillRect +CONSOLE MESSAGE: method getLineDash +CONSOLE MESSAGE: method getTransform +CONSOLE MESSAGE: method isPointInPath +CONSOLE MESSAGE: method isPointInStroke +CONSOLE MESSAGE: method lineTo +CONSOLE MESSAGE: method moveTo +CONSOLE MESSAGE: method quadraticCurveTo +CONSOLE MESSAGE: method rect +CONSOLE MESSAGE: method reset +CONSOLE MESSAGE: method resetTransform +CONSOLE MESSAGE: method restore +CONSOLE MESSAGE: method rotate +CONSOLE MESSAGE: method roundRect +CONSOLE MESSAGE: method save +CONSOLE MESSAGE: method scale +CONSOLE MESSAGE: method setLineDash +CONSOLE MESSAGE: method setTransform +CONSOLE MESSAGE: method stroke +CONSOLE MESSAGE: method strokeRect +CONSOLE MESSAGE: method transform +CONSOLE MESSAGE: method translate +CONSOLE MESSAGE: setter fillStyle +CONSOLE MESSAGE: setter filter +CONSOLE MESSAGE: setter globalAlpha +CONSOLE MESSAGE: setter globalCompositeOperation +CONSOLE MESSAGE: setter imageSmoothingEnabled +CONSOLE MESSAGE: setter lineCap +CONSOLE MESSAGE: setter lineDashOffset +CONSOLE MESSAGE: setter lineJoin +CONSOLE MESSAGE: setter lineWidth +CONSOLE MESSAGE: setter miterLimit +CONSOLE MESSAGE: setter shadowBlur +CONSOLE MESSAGE: setter shadowColor +CONSOLE MESSAGE: setter shadowOffsetX +CONSOLE MESSAGE: setter shadowOffsetY +CONSOLE MESSAGE: setter strokeStyle +CONSOLE MESSAGE: interface PaintSize +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter height +CONSOLE MESSAGE: getter width +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface PaintWorkletGlobalScope : WorkletGlobalScope +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface Path2D +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method addPath +CONSOLE MESSAGE: method arc +CONSOLE MESSAGE: method arcTo +CONSOLE MESSAGE: method bezierCurveTo +CONSOLE MESSAGE: method closePath +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method ellipse +CONSOLE MESSAGE: method lineTo +CONSOLE MESSAGE: method moveTo +CONSOLE MESSAGE: method quadraticCurveTo +CONSOLE MESSAGE: method rect +CONSOLE MESSAGE: method roundRect +CONSOLE MESSAGE: interface ReadableByteStreamController +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter byobRequest +CONSOLE MESSAGE: getter desiredSize +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method enqueue +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: interface ReadableStream +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter locked +CONSOLE MESSAGE: method cancel +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method getReader +CONSOLE MESSAGE: method pipeThrough +CONSOLE MESSAGE: method pipeTo +CONSOLE MESSAGE: method tee +CONSOLE MESSAGE: interface ReadableStreamBYOBReader +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter closed +CONSOLE MESSAGE: method cancel +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method read +CONSOLE MESSAGE: method releaseLock +CONSOLE MESSAGE: interface ReadableStreamBYOBRequest +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter view +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method respond +CONSOLE MESSAGE: method respondWithNewView +CONSOLE MESSAGE: interface ReadableStreamDefaultController +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter desiredSize +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method enqueue +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: interface ReadableStreamDefaultReader +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter closed +CONSOLE MESSAGE: method cancel +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method read +CONSOLE MESSAGE: method releaseLock +CONSOLE MESSAGE: interface StylePropertyMapReadOnly +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter size +CONSOLE MESSAGE: method @@iterator +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method entries +CONSOLE MESSAGE: method forEach +CONSOLE MESSAGE: method get +CONSOLE MESSAGE: method getAll +CONSOLE MESSAGE: method has +CONSOLE MESSAGE: method keys +CONSOLE MESSAGE: method values +CONSOLE MESSAGE: interface TransformStream +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter readable +CONSOLE MESSAGE: getter writable +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface WorkletGlobalScope +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: interface WritableStream +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter locked +CONSOLE MESSAGE: method abort +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method getWriter +CONSOLE MESSAGE: interface WritableStreamDefaultController +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter signal +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method error +CONSOLE MESSAGE: interface WritableStreamDefaultWriter +CONSOLE MESSAGE: attribute @@toStringTag +CONSOLE MESSAGE: getter closed +CONSOLE MESSAGE: getter desiredSize +CONSOLE MESSAGE: getter ready +CONSOLE MESSAGE: method abort +CONSOLE MESSAGE: method close +CONSOLE MESSAGE: method constructor +CONSOLE MESSAGE: method releaseLock +CONSOLE MESSAGE: method write +CONSOLE MESSAGE: [NAMESPACES] +CONSOLE MESSAGE: [GLOBAL OBJECT] +CONSOLE MESSAGE: attribute console +CONSOLE MESSAGE: attribute globalThis +CONSOLE MESSAGE: getter devicePixelRatio +CONSOLE MESSAGE: method gc +CONSOLE MESSAGE: method registerPaint +
diff --git a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt index 35afa391..6685fee 100644 --- a/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt +++ b/third_party/blink/web_tests/webexposed/feature-policy-features-expected.txt
@@ -15,7 +15,6 @@ ch-ua ch-ua-arch ch-ua-bitness -ch-ua-full ch-ua-full-version ch-ua-full-version-list ch-ua-mobile
diff --git a/third_party/nearby/BUILD.gn b/third_party/nearby/BUILD.gn index 4f814d7a..0ba8944 100644 --- a/third_party/nearby/BUILD.gn +++ b/third_party/nearby/BUILD.gn
@@ -1,10 +1,8 @@ # Copyright 2020 The Chromium Authors. All rights reserved. # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. - import("//build/util/process_version.gni") import("//third_party/protobuf/proto_library.gni") - if (is_chromeos_device) { import("//build/config/chromeos/rules.gni") } @@ -13,7 +11,6 @@ config("nearby_include_config") { include_dirs = [ "src", - "src/cpp", "$root_gen_dir/third_party/nearby", # For WebRTC APIs. @@ -41,9 +38,9 @@ public = [ "src/internal/analytics/analytics_recorder.h" ] public_deps = [ ":connections_enums_proto", + ":connections_event_logger", ":connections_log_proto", - ":core_event_logger", - ":core_types", + ":connections_types", ":error_code_enums_proto", ":platform_base", ":platform_base_error_code_recorder", @@ -56,21 +53,21 @@ } ############################################################################### -# src/cpp/core +# src/connections ############################################################################### -# src/cpp/core -source_set("core") { +# src/connections +source_set("connections") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] - sources = [ "src/cpp/core/core.cc" ] - public = [ "src/cpp/core/core.h" ] + sources = [ "src/connections/core.cc" ] + public = [ "src/connections/core.h" ] public_deps = [ ":connections_enums_proto", - ":core_event_logger", - ":core_internal", - ":core_types", + ":connections_event_logger", + ":connections_implementation", + ":connections_types", ":platform_public_comm", ":platform_public_logging", ":platform_public_types", @@ -79,30 +76,30 @@ configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } -source_set("core_types") { +source_set("connections_types") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] sources = [ - "src/cpp/core/advertising_options.cc", - "src/cpp/core/connection_options.cc", - "src/cpp/core/discovery_options.cc", - "src/cpp/core/payload.cc", - "src/cpp/core/strategy.cc", + "src/connections/advertising_options.cc", + "src/connections/connection_options.cc", + "src/connections/discovery_options.cc", + "src/connections/payload.cc", + "src/connections/strategy.cc", ] public = [ - "src/cpp/core/advertising_options.h", - "src/cpp/core/connection_options.h", - "src/cpp/core/discovery_options.h", - "src/cpp/core/listeners.h", - "src/cpp/core/options_base.h", - "src/cpp/core/out_of_band_connection_metadata.h", - "src/cpp/core/params.h", - "src/cpp/core/payload.h", - "src/cpp/core/power_level.h", - "src/cpp/core/status.h", - "src/cpp/core/strategy.h", + "src/connections/advertising_options.h", + "src/connections/connection_options.h", + "src/connections/discovery_options.h", + "src/connections/listeners.h", + "src/connections/options_base.h", + "src/connections/out_of_band_connection_metadata.h", + "src/connections/params.h", + "src/connections/payload.h", + "src/connections/power_level.h", + "src/connections/status.h", + "src/connections/strategy.h", ] public_deps = [ ":connections_enums_proto", @@ -115,98 +112,98 @@ configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } -source_set("core_event_logger") { +source_set("connections_event_logger") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] - public = [ "src/cpp/core/event_logger.h" ] + public = [ "src/connections/event_logger.h" ] public_deps = [ ":connections_log_proto" ] configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } -# src/cpp/core/internal -source_set("core_internal") { +# src/connections/implementation +source_set("connections_implementation") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] sources = [ - "src/cpp/core/internal/base_endpoint_channel.cc", - "src/cpp/core/internal/base_pcp_handler.cc", - "src/cpp/core/internal/ble_advertisement.cc", - "src/cpp/core/internal/ble_endpoint_channel.cc", - "src/cpp/core/internal/bluetooth_bwu_handler.cc", - "src/cpp/core/internal/bluetooth_device_name.cc", - "src/cpp/core/internal/bluetooth_endpoint_channel.cc", - "src/cpp/core/internal/bwu_manager.cc", - "src/cpp/core/internal/client_proxy.cc", - "src/cpp/core/internal/encryption_runner.cc", - "src/cpp/core/internal/endpoint_channel_manager.cc", - "src/cpp/core/internal/endpoint_manager.cc", - "src/cpp/core/internal/injected_bluetooth_device_store.cc", - "src/cpp/core/internal/internal_payload.cc", - "src/cpp/core/internal/internal_payload_factory.cc", - "src/cpp/core/internal/offline_frames.cc", - "src/cpp/core/internal/offline_frames_validator.cc", - "src/cpp/core/internal/offline_service_controller.cc", - "src/cpp/core/internal/p2p_cluster_pcp_handler.cc", - "src/cpp/core/internal/p2p_point_to_point_pcp_handler.cc", - "src/cpp/core/internal/p2p_star_pcp_handler.cc", - "src/cpp/core/internal/payload_manager.cc", - "src/cpp/core/internal/pcp_manager.cc", - "src/cpp/core/internal/service_controller_router.cc", - "src/cpp/core/internal/webrtc_bwu_handler.cc", - "src/cpp/core/internal/webrtc_endpoint_channel.cc", - "src/cpp/core/internal/wifi_lan_bwu_handler.cc", - "src/cpp/core/internal/wifi_lan_endpoint_channel.cc", - "src/cpp/core/internal/wifi_lan_service_info.cc", + "src/connections/implementation/base_endpoint_channel.cc", + "src/connections/implementation/base_pcp_handler.cc", + "src/connections/implementation/ble_advertisement.cc", + "src/connections/implementation/ble_endpoint_channel.cc", + "src/connections/implementation/bluetooth_bwu_handler.cc", + "src/connections/implementation/bluetooth_device_name.cc", + "src/connections/implementation/bluetooth_endpoint_channel.cc", + "src/connections/implementation/bwu_manager.cc", + "src/connections/implementation/client_proxy.cc", + "src/connections/implementation/encryption_runner.cc", + "src/connections/implementation/endpoint_channel_manager.cc", + "src/connections/implementation/endpoint_manager.cc", + "src/connections/implementation/injected_bluetooth_device_store.cc", + "src/connections/implementation/internal_payload.cc", + "src/connections/implementation/internal_payload_factory.cc", + "src/connections/implementation/offline_frames.cc", + "src/connections/implementation/offline_frames_validator.cc", + "src/connections/implementation/offline_service_controller.cc", + "src/connections/implementation/p2p_cluster_pcp_handler.cc", + "src/connections/implementation/p2p_point_to_point_pcp_handler.cc", + "src/connections/implementation/p2p_star_pcp_handler.cc", + "src/connections/implementation/payload_manager.cc", + "src/connections/implementation/pcp_manager.cc", + "src/connections/implementation/service_controller_router.cc", + "src/connections/implementation/webrtc_bwu_handler.cc", + "src/connections/implementation/webrtc_endpoint_channel.cc", + "src/connections/implementation/wifi_lan_bwu_handler.cc", + "src/connections/implementation/wifi_lan_endpoint_channel.cc", + "src/connections/implementation/wifi_lan_service_info.cc", ] public = [ - "src/cpp/core/internal/base_bwu_handler.h", - "src/cpp/core/internal/base_endpoint_channel.h", - "src/cpp/core/internal/base_pcp_handler.h", - "src/cpp/core/internal/ble_advertisement.h", - "src/cpp/core/internal/ble_endpoint_channel.h", - "src/cpp/core/internal/bluetooth_bwu_handler.h", - "src/cpp/core/internal/bluetooth_device_name.h", - "src/cpp/core/internal/bluetooth_endpoint_channel.h", - "src/cpp/core/internal/bwu_handler.h", - "src/cpp/core/internal/bwu_manager.h", - "src/cpp/core/internal/client_proxy.h", - "src/cpp/core/internal/encryption_runner.h", - "src/cpp/core/internal/endpoint_channel.h", - "src/cpp/core/internal/endpoint_channel_manager.h", - "src/cpp/core/internal/endpoint_manager.h", - "src/cpp/core/internal/injected_bluetooth_device_store.h", - "src/cpp/core/internal/internal_payload.h", - "src/cpp/core/internal/internal_payload_factory.h", - "src/cpp/core/internal/message_lite.h", - "src/cpp/core/internal/offline_frames.h", - "src/cpp/core/internal/offline_frames_validator.h", - "src/cpp/core/internal/offline_service_controller.h", - "src/cpp/core/internal/p2p_cluster_pcp_handler.h", - "src/cpp/core/internal/p2p_point_to_point_pcp_handler.h", - "src/cpp/core/internal/p2p_star_pcp_handler.h", - "src/cpp/core/internal/payload_manager.h", - "src/cpp/core/internal/pcp.h", - "src/cpp/core/internal/pcp_handler.h", - "src/cpp/core/internal/pcp_manager.h", - "src/cpp/core/internal/service_controller.h", - "src/cpp/core/internal/service_controller_router.h", - "src/cpp/core/internal/webrtc_bwu_handler.h", - "src/cpp/core/internal/webrtc_endpoint_channel.h", - "src/cpp/core/internal/wifi_lan_bwu_handler.h", - "src/cpp/core/internal/wifi_lan_endpoint_channel.h", - "src/cpp/core/internal/wifi_lan_service_info.h", + "src/connections/implementation/base_bwu_handler.h", + "src/connections/implementation/base_endpoint_channel.h", + "src/connections/implementation/base_pcp_handler.h", + "src/connections/implementation/ble_advertisement.h", + "src/connections/implementation/ble_endpoint_channel.h", + "src/connections/implementation/bluetooth_bwu_handler.h", + "src/connections/implementation/bluetooth_device_name.h", + "src/connections/implementation/bluetooth_endpoint_channel.h", + "src/connections/implementation/bwu_handler.h", + "src/connections/implementation/bwu_manager.h", + "src/connections/implementation/client_proxy.h", + "src/connections/implementation/encryption_runner.h", + "src/connections/implementation/endpoint_channel.h", + "src/connections/implementation/endpoint_channel_manager.h", + "src/connections/implementation/endpoint_manager.h", + "src/connections/implementation/injected_bluetooth_device_store.h", + "src/connections/implementation/internal_payload.h", + "src/connections/implementation/internal_payload_factory.h", + "src/connections/implementation/message_lite.h", + "src/connections/implementation/offline_frames.h", + "src/connections/implementation/offline_frames_validator.h", + "src/connections/implementation/offline_service_controller.h", + "src/connections/implementation/p2p_cluster_pcp_handler.h", + "src/connections/implementation/p2p_point_to_point_pcp_handler.h", + "src/connections/implementation/p2p_star_pcp_handler.h", + "src/connections/implementation/payload_manager.h", + "src/connections/implementation/pcp.h", + "src/connections/implementation/pcp_handler.h", + "src/connections/implementation/pcp_manager.h", + "src/connections/implementation/service_controller.h", + "src/connections/implementation/service_controller_router.h", + "src/connections/implementation/webrtc_bwu_handler.h", + "src/connections/implementation/webrtc_endpoint_channel.h", + "src/connections/implementation/wifi_lan_bwu_handler.h", + "src/connections/implementation/wifi_lan_endpoint_channel.h", + "src/connections/implementation/wifi_lan_service_info.h", ] public_deps = [ ":analytics", ":connections_enums_proto", - ":core_internal_mediums", - ":core_internal_mediums_webrtc", - ":core_types", + ":connections_implementation_mediums", + ":connections_implementation_mediums_webrtc", + ":connections_types", ":offline_wire_formats_proto", ":platform_base", ":platform_base_cancellation_flag", @@ -222,59 +219,58 @@ configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } - -source_set("core_internal_test") { +source_set("connections_test_util") { testonly = true public_configs = [ ":nearby_include_config", ":nearby_defines", ] - public = [ "src/cpp/core/internal/mock_service_controller_router.h" ] + public = [ "src/connections/implementation/mock_service_controller_router.h" ] deps = [ - ":core_internal", + ":connections_implementation", "//third_party/googletest:gmock", ] } -# src/cpp/core/internal/mediums -source_set("core_internal_mediums") { +# src/connections/implementation/mediums +source_set("connections_implementation_mediums") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] sources = [ - "src/cpp/core/internal/mediums/ble.cc", - "src/cpp/core/internal/mediums/ble_v2/advertisement_read_result.cc", - "src/cpp/core/internal/mediums/ble_v2/ble_advertisement.cc", - "src/cpp/core/internal/mediums/ble_v2/ble_advertisement_header.cc", - "src/cpp/core/internal/mediums/ble_v2/ble_packet.cc", - "src/cpp/core/internal/mediums/ble_v2/bloom_filter.cc", - "src/cpp/core/internal/mediums/bluetooth_classic.cc", - "src/cpp/core/internal/mediums/bluetooth_radio.cc", - "src/cpp/core/internal/mediums/mediums.cc", - "src/cpp/core/internal/mediums/uuid.cc", - "src/cpp/core/internal/mediums/webrtc.cc", - "src/cpp/core/internal/mediums/wifi_lan.cc", + "src/connections/implementation/mediums/ble.cc", + "src/connections/implementation/mediums/ble_v2/advertisement_read_result.cc", + "src/connections/implementation/mediums/ble_v2/ble_advertisement.cc", + "src/connections/implementation/mediums/ble_v2/ble_advertisement_header.cc", + "src/connections/implementation/mediums/ble_v2/ble_packet.cc", + "src/connections/implementation/mediums/ble_v2/bloom_filter.cc", + "src/connections/implementation/mediums/bluetooth_classic.cc", + "src/connections/implementation/mediums/bluetooth_radio.cc", + "src/connections/implementation/mediums/mediums.cc", + "src/connections/implementation/mediums/uuid.cc", + "src/connections/implementation/mediums/webrtc.cc", + "src/connections/implementation/mediums/wifi_lan.cc", ] public = [ - "src/cpp/core/internal/mediums/ble.h", - "src/cpp/core/internal/mediums/ble_v2/advertisement_read_result.h", - "src/cpp/core/internal/mediums/ble_v2/ble_advertisement.h", - "src/cpp/core/internal/mediums/ble_v2/ble_advertisement_header.h", - "src/cpp/core/internal/mediums/ble_v2/ble_packet.h", - "src/cpp/core/internal/mediums/ble_v2/ble_peripheral.h", - "src/cpp/core/internal/mediums/ble_v2/bloom_filter.h", - "src/cpp/core/internal/mediums/bluetooth_classic.h", - "src/cpp/core/internal/mediums/bluetooth_radio.h", - "src/cpp/core/internal/mediums/lost_entity_tracker.h", - "src/cpp/core/internal/mediums/mediums.h", - "src/cpp/core/internal/mediums/uuid.h", - "src/cpp/core/internal/mediums/webrtc.h", - "src/cpp/core/internal/mediums/wifi_lan.h", + "src/connections/implementation/mediums/ble.h", + "src/connections/implementation/mediums/ble_v2/advertisement_read_result.h", + "src/connections/implementation/mediums/ble_v2/ble_advertisement.h", + "src/connections/implementation/mediums/ble_v2/ble_advertisement_header.h", + "src/connections/implementation/mediums/ble_v2/ble_packet.h", + "src/connections/implementation/mediums/ble_v2/ble_peripheral.h", + "src/connections/implementation/mediums/ble_v2/bloom_filter.h", + "src/connections/implementation/mediums/bluetooth_classic.h", + "src/connections/implementation/mediums/bluetooth_radio.h", + "src/connections/implementation/mediums/lost_entity_tracker.h", + "src/connections/implementation/mediums/mediums.h", + "src/connections/implementation/mediums/uuid.h", + "src/connections/implementation/mediums/webrtc.h", + "src/connections/implementation/mediums/wifi_lan.h", ] public_deps = [ - ":core_internal_mediums_webrtc", - ":core_types", + ":connections_implementation_mediums_webrtc", + ":connections_types", ":platform_base", ":platform_base_cancellation_flag", ":platform_base_util", @@ -289,23 +285,23 @@ configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } -source_set("core_internal_mediums_utils") { +source_set("connections_implementation_mediums_utils") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] sources = [ - "src/cpp/core/internal/mediums/utils.cc", - "src/cpp/core/internal/mediums/webrtc_peer_id.cc", + "src/connections/implementation/mediums/utils.cc", + "src/connections/implementation/mediums/webrtc_peer_id.cc", ] public = [ "//third_party/abseil-cpp:absl", - "src/cpp/core/internal/mediums/utils.h", - "src/cpp/core/internal/mediums/webrtc_peer_id.h", - "src/cpp/core/internal/mediums/webrtc_socket.h", + "src/connections/implementation/mediums/utils.h", + "src/connections/implementation/mediums/webrtc_peer_id.h", + "src/connections/implementation/mediums/webrtc_socket.h", ] public_deps = [ - ":core_internal_mediums_webrtc_data_types", + ":connections_implementation_mediums_webrtc_data_types", ":offline_wire_formats_proto", ":platform_base", ":platform_public_types", @@ -313,15 +309,17 @@ configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } -source_set("core_internal_mediums_webrtc_data_types") { +source_set("connections_implementation_mediums_webrtc_data_types") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] - sources = [ "src/cpp/core/internal/mediums/webrtc/webrtc_socket_impl.cc" ] - public = [ "src/cpp/core/internal/mediums/webrtc/webrtc_socket_impl.h" ] + sources = + [ "src/connections/implementation/mediums/webrtc/webrtc_socket_impl.cc" ] + public = + [ "src/connections/implementation/mediums/webrtc/webrtc_socket_impl.h" ] public_deps = [ - ":core_types", + ":connections_types", ":platform_base", ":platform_public_types", "//third_party/webrtc_overrides:webrtc_component", @@ -329,26 +327,26 @@ configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ] } -source_set("core_internal_mediums_webrtc") { +source_set("connections_implementation_mediums_webrtc") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] sources = [ - "src/cpp/core/internal/mediums/webrtc/connection_flow.cc", - "src/cpp/core/internal/mediums/webrtc/signaling_frames.cc", + "src/connections/implementation/mediums/webrtc/connection_flow.cc", + "src/connections/implementation/mediums/webrtc/signaling_frames.cc", ] public = [ - "src/cpp/core/internal/mediums/webrtc/connection_flow.h", - "src/cpp/core/internal/mediums/webrtc/data_channel_listener.h", - "src/cpp/core/internal/mediums/webrtc/local_ice_candidate_listener.h", - "src/cpp/core/internal/mediums/webrtc/session_description_wrapper.h", - "src/cpp/core/internal/mediums/webrtc/signaling_frames.h", + "src/connections/implementation/mediums/webrtc/connection_flow.h", + "src/connections/implementation/mediums/webrtc/data_channel_listener.h", + "src/connections/implementation/mediums/webrtc/local_ice_candidate_listener.h", + "src/connections/implementation/mediums/webrtc/session_description_wrapper.h", + "src/connections/implementation/mediums/webrtc/signaling_frames.h", ] public_deps = [ - ":core_internal_mediums_utils", - ":core_internal_mediums_webrtc_data_types", - ":core_types", + ":connections_implementation_mediums_utils", + ":connections_implementation_mediums_webrtc_data_types", + ":connections_types", ":platform_base", ":platform_public_comm", ":platform_public_logging", @@ -362,23 +360,23 @@ } ############################################################################### -# src/cpp/platform +# src/internal/platform ############################################################################### -# src/cpp/platform/api +# src/internal/platform/implementation source_set("platform_api_comm") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] sources = [ - "src/cpp/platform/api/ble.h", - "src/cpp/platform/api/ble_v2.h", - "src/cpp/platform/api/bluetooth_adapter.h", - "src/cpp/platform/api/bluetooth_classic.h", - "src/cpp/platform/api/server_sync.h", - "src/cpp/platform/api/webrtc.h", - "src/cpp/platform/api/wifi.h", - "src/cpp/platform/api/wifi_lan.h", + "src/internal/platform/implementation/ble.h", + "src/internal/platform/implementation/ble_v2.h", + "src/internal/platform/implementation/bluetooth_adapter.h", + "src/internal/platform/implementation/bluetooth_classic.h", + "src/internal/platform/implementation/server_sync.h", + "src/internal/platform/implementation/webrtc.h", + "src/internal/platform/implementation/wifi.h", + "src/internal/platform/implementation/wifi_lan.h", ] public_deps = [ ":offline_wire_formats_proto", @@ -396,23 +394,23 @@ ":nearby_defines", ] sources = [ - "src/cpp/platform/api/atomic_boolean.h", - "src/cpp/platform/api/atomic_reference.h", - "src/cpp/platform/api/cancelable.h", - "src/cpp/platform/api/condition_variable.h", - "src/cpp/platform/api/count_down_latch.h", - "src/cpp/platform/api/crypto.h", - "src/cpp/platform/api/executor.h", - "src/cpp/platform/api/future.h", - "src/cpp/platform/api/input_file.h", - "src/cpp/platform/api/listenable_future.h", - "src/cpp/platform/api/log_message.h", - "src/cpp/platform/api/mutex.h", - "src/cpp/platform/api/output_file.h", - "src/cpp/platform/api/scheduled_executor.h", - "src/cpp/platform/api/settable_future.h", - "src/cpp/platform/api/submittable_executor.h", - "src/cpp/platform/api/system_clock.h", + "src/internal/platform/implementation/atomic_boolean.h", + "src/internal/platform/implementation/atomic_reference.h", + "src/internal/platform/implementation/cancelable.h", + "src/internal/platform/implementation/condition_variable.h", + "src/internal/platform/implementation/count_down_latch.h", + "src/internal/platform/implementation/crypto.h", + "src/internal/platform/implementation/executor.h", + "src/internal/platform/implementation/future.h", + "src/internal/platform/implementation/input_file.h", + "src/internal/platform/implementation/listenable_future.h", + "src/internal/platform/implementation/log_message.h", + "src/internal/platform/implementation/mutex.h", + "src/internal/platform/implementation/output_file.h", + "src/internal/platform/implementation/scheduled_executor.h", + "src/internal/platform/implementation/settable_future.h", + "src/internal/platform/implementation/submittable_executor.h", + "src/internal/platform/implementation/system_clock.h", ] public_deps = [ ":platform_base", @@ -426,7 +424,7 @@ ":nearby_include_config", ":nearby_defines", ] - public = [ "src/cpp/platform/api/platform.h" ] + public = [ "src/internal/platform/implementation/platform.h" ] public_deps = [ ":platform_api_comm", ":platform_api_types", @@ -437,35 +435,35 @@ configs += [ "//build/config/compiler:no_chromium_code" ] } -# src/cpp/platform/base +# src/internal/platform source_set("platform_base") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] sources = [ - "src/cpp/platform/base/base64_utils.cc", - "src/cpp/platform/base/bluetooth_utils.cc", - "src/cpp/platform/base/input_stream.cc", - "src/cpp/platform/base/nsd_service_info.cc", - "src/cpp/platform/base/prng.cc", + "src/internal/platform/base64_utils.cc", + "src/internal/platform/bluetooth_utils.cc", + "src/internal/platform/input_stream.cc", + "src/internal/platform/nsd_service_info.cc", + "src/internal/platform/prng.cc", ] public = [ - "src/cpp/platform/base/base64_utils.h", - "src/cpp/platform/base/bluetooth_utils.h", - "src/cpp/platform/base/byte_array.h", - "src/cpp/platform/base/callable.h", - "src/cpp/platform/base/exception.h", - "src/cpp/platform/base/feature_flags.h", - "src/cpp/platform/base/input_stream.h", - "src/cpp/platform/base/listeners.h", - "src/cpp/platform/base/nsd_service_info.h", - "src/cpp/platform/base/output_stream.h", - "src/cpp/platform/base/payload_id.h", - "src/cpp/platform/base/prng.h", - "src/cpp/platform/base/runnable.h", - "src/cpp/platform/base/socket.h", - "src/cpp/platform/base/types.h", + "src/internal/platform/base64_utils.h", + "src/internal/platform/bluetooth_utils.h", + "src/internal/platform/byte_array.h", + "src/internal/platform/callable.h", + "src/internal/platform/exception.h", + "src/internal/platform/feature_flags.h", + "src/internal/platform/input_stream.h", + "src/internal/platform/listeners.h", + "src/internal/platform/nsd_service_info.h", + "src/internal/platform/output_stream.h", + "src/internal/platform/payload_id.h", + "src/internal/platform/prng.h", + "src/internal/platform/runnable.h", + "src/internal/platform/socket.h", + "src/internal/platform/types.h", ] public_deps = [ "//third_party/abseil-cpp:absl" ] configs -= [ "//build/config/compiler:chromium_code" ] @@ -476,10 +474,10 @@ ":nearby_include_config", ":nearby_defines", ] - sources = [ "src/cpp/platform/base/error_code_recorder.cc" ] + sources = [ "src/internal/platform/error_code_recorder.cc" ] public = [ - "src/cpp/platform/base/error_code_params.h", - "src/cpp/platform/base/error_code_recorder.h", + "src/internal/platform/error_code_params.h", + "src/internal/platform/error_code_recorder.h", ] public_deps = [ ":connections_enums_proto", @@ -495,13 +493,13 @@ ":nearby_defines", ] sources = [ - "src/cpp/platform/base/base_input_stream.cc", - "src/cpp/platform/base/base_pipe.cc", + "src/internal/platform/base_input_stream.cc", + "src/internal/platform/base_pipe.cc", ] public = [ - "src/cpp/platform/base/base_input_stream.h", - "src/cpp/platform/base/base_mutex_lock.h", - "src/cpp/platform/base/base_pipe.h", + "src/internal/platform/base_input_stream.h", + "src/internal/platform/base_mutex_lock.h", + "src/internal/platform/base_pipe.h", ] public_deps = [ ":platform_api_types", @@ -516,7 +514,7 @@ ":nearby_include_config", ":nearby_defines", ] - public = [ "src/cpp/platform/base/logging.h" ] + public = [ "src/internal/platform/logging.h" ] public_deps = [ ":platform_api_platform", ":platform_api_types", @@ -530,8 +528,8 @@ ":nearby_include_config", ":nearby_defines", ] - sources = [ "src/cpp/platform/base/cancellation_flag.cc" ] - public = [ "src/cpp/platform/base/cancellation_flag.h" ] + sources = [ "src/internal/platform/cancellation_flag.cc" ] + public = [ "src/internal/platform/cancellation_flag.h" ] public_deps = [ ":platform_base", ":platform_base_util", @@ -541,14 +539,14 @@ configs += [ "//build/config/compiler:no_chromium_code" ] } -# src/cpp/platform/impl/shared +# src/internal/platform/implementation/shared source_set("platform_impl_shared_file") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] - sources = [ "src/cpp/platform/impl/shared/file.cc" ] - public = [ "src/cpp/platform/impl/shared/file.h" ] + sources = [ "src/internal/platform/implementation/shared/file.cc" ] + public = [ "src/internal/platform/implementation/shared/file.h" ] public_deps = [ ":platform_api_platform", ":platform_public_types", @@ -558,39 +556,39 @@ configs += [ "//build/config/compiler:no_chromium_code" ] } -# src/cpp/platform/public +# src/internal/platform source_set("platform_public_types") { public_configs = [ ":nearby_include_config", ":nearby_defines", ] sources = [ - "src/cpp/platform/public/monitored_runnable.cc", - "src/cpp/platform/public/pending_job_registry.cc", - "src/cpp/platform/public/pipe.cc", + "src/internal/platform/monitored_runnable.cc", + "src/internal/platform/pending_job_registry.cc", + "src/internal/platform/pipe.cc", ] public = [ - "src/cpp/platform/public/atomic_boolean.h", - "src/cpp/platform/public/atomic_reference.h", - "src/cpp/platform/public/cancelable.h", - "src/cpp/platform/public/cancelable_alarm.h", - "src/cpp/platform/public/condition_variable.h", - "src/cpp/platform/public/count_down_latch.h", - "src/cpp/platform/public/crypto.h", - "src/cpp/platform/public/file.h", - "src/cpp/platform/public/future.h", - "src/cpp/platform/public/logging.h", - "src/cpp/platform/public/monitored_runnable.h", - "src/cpp/platform/public/multi_thread_executor.h", - "src/cpp/platform/public/mutex.h", - "src/cpp/platform/public/mutex_lock.h", - "src/cpp/platform/public/pending_job_registry.h", - "src/cpp/platform/public/pipe.h", - "src/cpp/platform/public/scheduled_executor.h", - "src/cpp/platform/public/settable_future.h", - "src/cpp/platform/public/single_thread_executor.h", - "src/cpp/platform/public/submittable_executor.h", - "src/cpp/platform/public/system_clock.h", + "src/internal/platform/atomic_boolean.h", + "src/internal/platform/atomic_reference.h", + "src/internal/platform/cancelable.h", + "src/internal/platform/cancelable_alarm.h", + "src/internal/platform/condition_variable.h", + "src/internal/platform/count_down_latch.h", + "src/internal/platform/crypto.h", + "src/internal/platform/file.h", + "src/internal/platform/future.h", + "src/internal/platform/logging.h", + "src/internal/platform/monitored_runnable.h", + "src/internal/platform/multi_thread_executor.h", + "src/internal/platform/mutex.h", + "src/internal/platform/mutex_lock.h", + "src/internal/platform/pending_job_registry.h", + "src/internal/platform/pipe.h", + "src/internal/platform/scheduled_executor.h", + "src/internal/platform/settable_future.h", + "src/internal/platform/single_thread_executor.h", + "src/internal/platform/submittable_executor.h", + "src/internal/platform/system_clock.h", ] public_deps = [ ":platform_api_platform", @@ -611,17 +609,17 @@ ":nearby_defines", ] sources = [ - "src/cpp/platform/public/ble.cc", - "src/cpp/platform/public/bluetooth_classic.cc", - "src/cpp/platform/public/file.cc", - "src/cpp/platform/public/wifi_lan.cc", + "src/internal/platform/ble.cc", + "src/internal/platform/bluetooth_classic.cc", + "src/internal/platform/file.cc", + "src/internal/platform/wifi_lan.cc", ] public = [ - "src/cpp/platform/public/ble.h", - "src/cpp/platform/public/bluetooth_adapter.h", - "src/cpp/platform/public/bluetooth_classic.h", - "src/cpp/platform/public/webrtc.h", - "src/cpp/platform/public/wifi_lan.h", + "src/internal/platform/ble.h", + "src/internal/platform/bluetooth_adapter.h", + "src/internal/platform/bluetooth_classic.h", + "src/internal/platform/webrtc.h", + "src/internal/platform/wifi_lan.h", ] public_deps = [ ":platform_api_comm", @@ -640,7 +638,7 @@ ":nearby_include_config", ":nearby_defines", ] - public = [ "src/cpp/platform/public/logging.h" ] + public = [ "src/internal/platform/logging.h" ] public_deps = [ ":platform_base_logging" ] configs -= [ "//build/config/compiler:chromium_code" ] configs += [ "//build/config/compiler:no_chromium_code" ]
diff --git a/third_party/nearby/README.chromium b/third_party/nearby/README.chromium index adc89ad..8325953 100644 --- a/third_party/nearby/README.chromium +++ b/third_party/nearby/README.chromium
@@ -1,7 +1,7 @@ Name: Nearby Connections Library Short Name: Nearby URL: https://github.com/google/nearby-connections -Version: 9d4ad8a1d72631640d5e4d0161e7fcf6b1d4f21d +Version: 42059a624b67ebb8d852248c49d0e121f9ad5d35 License: Apache 2.0 License File: LICENSE Security Critical: yes
diff --git a/third_party/tflite/README.chromium b/third_party/tflite/README.chromium index 25c18f2c..effbf629 100644 --- a/third_party/tflite/README.chromium +++ b/third_party/tflite/README.chromium
@@ -1,8 +1,8 @@ Name: TensorFlow Lite Short Name: tflite URL: https://github.com/tensorflow/tensorflow -Version: d570144d42b17065ea1c222e9ea38fa1810bee21 -Date: 2022/01/31 +Version: d9e5d3c634c2ab1221e7d30b562c48b0b0e110b7 +Date: 2022/02/07 License: Apache 2.0 License File: LICENSE Security Critical: Yes
diff --git a/third_party/tflite_support/BUILD.gn b/third_party/tflite_support/BUILD.gn index 30f80c0b..6d9c6a0 100644 --- a/third_party/tflite_support/BUILD.gn +++ b/third_party/tflite_support/BUILD.gn
@@ -71,15 +71,20 @@ "src/tensorflow_lite_support/cc/task/core/external_file_handler.cc", "src/tensorflow_lite_support/cc/task/core/external_file_handler.h", "src/tensorflow_lite_support/cc/task/core/proto/external_file_proto_inc.h", + "src/tensorflow_lite_support/cc/task/core/task_api_factory.cc", "src/tensorflow_lite_support/cc/task/core/task_api_factory.h", "src/tensorflow_lite_support/cc/task/core/task_utils.cc", "src/tensorflow_lite_support/cc/task/core/task_utils.h", "src/tensorflow_lite_support/cc/task/core/tflite_engine.cc", "src/tensorflow_lite_support/cc/task/core/tflite_engine.h", + "src/tensorflow_lite_support/cc/task/processor/bert_preprocessor.cc", + "src/tensorflow_lite_support/cc/task/processor/bert_preprocessor.h", "src/tensorflow_lite_support/cc/task/processor/image_preprocessor.cc", "src/tensorflow_lite_support/cc/task/processor/image_preprocessor.h", "src/tensorflow_lite_support/cc/task/processor/processor.cc", "src/tensorflow_lite_support/cc/task/processor/processor.h", + "src/tensorflow_lite_support/cc/task/processor/regex_preprocessor.cc", + "src/tensorflow_lite_support/cc/task/processor/regex_preprocessor.h", "src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.cc", "src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.h", "src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.cc",
diff --git a/third_party/tflite_support/README.chromium b/third_party/tflite_support/README.chromium index 4995893e..31a08ca 100644 --- a/third_party/tflite_support/README.chromium +++ b/third_party/tflite_support/README.chromium
@@ -1,8 +1,8 @@ Name: TensorFlow Lite Support Short Name: tflite-support URL: https://github.com/tensorflow/tflite-support -Version: v0.3.1 -Date: 2021/12/16 +Version: 27decd8a9f30004d01b1cd5f40f27e7b1be20fa5 +Date: 2022/02/07 License: Apache 2.0 License File: LICENSE Security Critical: Yes @@ -30,13 +30,13 @@ 06) [To Be Upstreamed] Remove unused variable in task_utils.h 07) Do not use absl::any since it is not supported in chromium 08) [To Be Upstreamed] Remove unused stl include in tokenizer_jni_lib.h -09) Remove unbuilt files that triggered checkdeps warnings, and fix file perms. -10) Remove memory mapped file support in external_file_handler.cc since it is +09) Remove memory mapped file support in external_file_handler.cc since it is only available on POSIX systems. -11) Run clang-format. +10) Run clang-format. +11) Remove unbuilt files that triggered checkdeps warnings, and fix file perms. 12) Remove an unneeded static initializer. -Update Process: +Update Process (internal: http://shortn/_nwz8liqimy): 1) Clone the tflite-support github repo at the desired commit into src/ 2) Apply each patch listed above residing in patches/ using `git apply patches/$PATCHFILE` 3) Get the build working.
diff --git a/third_party/tflite_support/patches/0001-use-re2-StringPiece-for-RegexTokenizer-Tokenize.patch b/third_party/tflite_support/patches/0001-use-re2-StringPiece-for-RegexTokenizer-Tokenize.patch index 950a6db..8524599 100644 --- a/third_party/tflite_support/patches/0001-use-re2-StringPiece-for-RegexTokenizer-Tokenize.patch +++ b/third_party/tflite_support/patches/0001-use-re2-StringPiece-for-RegexTokenizer-Tokenize.patch
@@ -1,7 +1,7 @@ -From b16b7af6f58ede0718fabf9c0da7495c79400c90 Mon Sep 17 00:00:00 2001 +From d421ebb9f37d777ab5315eb2c59a5e21e06459e0 Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Wed, 15 Dec 2021 14:39:48 -0800 -Subject: [PATCH 01/11] use re2 StringPiece for RegexTokenizer::Tokenize +Date: Mon, 7 Feb 2022 12:09:19 -0800 +Subject: [PATCH 01/12] use re2 StringPiece for RegexTokenizer Tokenize --- .../cc/text/tokenizers/regex_tokenizer.cc | 8 ++++---- @@ -32,5 +32,5 @@ bool has_non_empty_token = token.length() > 0; -- -2.34.1.307.g9b7440fafd-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/patches/0002-sentencepiece-tokenization-not-supported.patch b/third_party/tflite_support/patches/0002-sentencepiece-tokenization-not-supported.patch index 95774a5..84bb277 100644 --- a/third_party/tflite_support/patches/0002-sentencepiece-tokenization-not-supported.patch +++ b/third_party/tflite_support/patches/0002-sentencepiece-tokenization-not-supported.patch
@@ -1,7 +1,7 @@ -From 9aa45ea43f8d84db1e20674c294f9ab958b12d7e Mon Sep 17 00:00:00 2001 +From 82dbaee5458261aea38947c38193f1e47ba553df Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Wed, 15 Dec 2021 14:57:16 -0800 -Subject: [PATCH 02/11] sentencepiece tokenization not supported +Date: Mon, 7 Feb 2022 12:09:37 -0800 +Subject: [PATCH 02/12] sentencepiece tokenization not supported --- .../cc/text/tokenizers/tokenizer_utils.cc | 14 ++++---------- @@ -47,5 +47,5 @@ case ProcessUnitOptions_RegexTokenizerOptions: { const tflite::RegexTokenizerOptions* options = -- -2.34.1.307.g9b7440fafd-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/patches/0003-rm-unused-func.patch b/third_party/tflite_support/patches/0003-rm-unused-func.patch index 5441faf..477f3bb 100644 --- a/third_party/tflite_support/patches/0003-rm-unused-func.patch +++ b/third_party/tflite_support/patches/0003-rm-unused-func.patch
@@ -1,7 +1,7 @@ -From 7bd2e5f0e2bb560e55efc3dd86249ff42a10d08c Mon Sep 17 00:00:00 2001 +From 9a8667b3d3be2ef20a88dfe9d50a1345d136da3e Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Wed, 15 Dec 2021 15:08:59 -0800 -Subject: [PATCH 03/11] rm unused func +Date: Mon, 7 Feb 2022 12:09:58 -0800 +Subject: [PATCH 03/12] rm unused func --- .../vision/utils/libyuv_frame_buffer_utils.cc | 201 +----------------- @@ -220,5 +220,5 @@ absl::Status LibyuvFrameBufferUtils::Crop(const FrameBuffer& buffer, int x0, int y0, int x1, int y1, -- -2.34.1.307.g9b7440fafd-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/patches/0004-rm-noop-deprecated-attribute.patch b/third_party/tflite_support/patches/0004-rm-noop-deprecated-attribute.patch index d59a5ad..2054644 100644 --- a/third_party/tflite_support/patches/0004-rm-noop-deprecated-attribute.patch +++ b/third_party/tflite_support/patches/0004-rm-noop-deprecated-attribute.patch
@@ -1,14 +1,14 @@ -From 243aadd7dcea9be980aa89d183bf2dea7cba202b Mon Sep 17 00:00:00 2001 +From b868bbc904b8ae8ff84ce8f96af6b9db13d138cb Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Wed, 15 Dec 2021 15:49:40 -0800 -Subject: [PATCH 04/11] rm noop deprecated attribute +Date: Mon, 7 Feb 2022 12:10:28 -0800 +Subject: [PATCH 04/12] rm noop deprecated attribute --- .../cc/task/text/nlclassifier/nl_classifier.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h -index d5b49dfd75277..ac12536355db4 100644 +index 74baa99f2752a..d97b2feb4d915 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h @@ -43,9 +43,6 @@ namespace text { @@ -22,5 +22,5 @@ int input_tensor_index = 0; int output_score_tensor_index = 0; -- -2.34.1.307.g9b7440fafd-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/patches/0005-use-size_t-in-for-loop.patch b/third_party/tflite_support/patches/0005-use-size_t-in-for-loop.patch index 015edf6f..bd11d4c 100644 --- a/third_party/tflite_support/patches/0005-use-size_t-in-for-loop.patch +++ b/third_party/tflite_support/patches/0005-use-size_t-in-for-loop.patch
@@ -1,25 +1,25 @@ -From 5d67933d8d4440816a02f7a319d7323041c3f7bf Mon Sep 17 00:00:00 2001 +From 5272c338771a1057bc52d830c85ec325cf545b0e Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Wed, 15 Dec 2021 15:51:22 -0800 -Subject: [PATCH 05/11] use size_t in for loop +Date: Mon, 7 Feb 2022 12:12:50 -0800 +Subject: [PATCH 05/12] use size_t in for loop --- .../cc/task/text/nlclassifier/nl_classifier.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h -index ac12536355db4..2adafba8f2fa9 100644 +index d97b2feb4d915..ab5126348f380 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h -@@ -179,7 +179,7 @@ class NLClassifier : public core::BaseTaskApi<std::vector<core::Category>, +@@ -194,7 +194,7 @@ class NLClassifier : public core::BaseTaskApi<std::vector<core::Category>, metadata_array, - const std::string& name, int index) { + const std::string& name, int default_index) { if (metadata_array != nullptr && metadata_array->size() == tensors.size()) { - for (int i = 0; i < metadata_array->size(); i++) { + for (size_t i = 0; i < metadata_array->size(); i++) { if (strcmp(name.data(), metadata_array->Get(i)->name()->c_str()) == 0) { - return tensors[i]; + return i; } -- -2.34.1.307.g9b7440fafd-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/patches/0006-unused-variable.patch b/third_party/tflite_support/patches/0006-unused-variable.patch index fa433fa..a9a05b58 100644 --- a/third_party/tflite_support/patches/0006-unused-variable.patch +++ b/third_party/tflite_support/patches/0006-unused-variable.patch
@@ -1,17 +1,17 @@ -From b2d06daf8ab5cff8748489407b6ad10ea600948d Mon Sep 17 00:00:00 2001 +From 09f5083d0c3b06b2cb32da9aa8eab503197015cb Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Thu, 16 Dec 2021 08:35:07 -0800 -Subject: [PATCH 06/11] unused variable +Date: Mon, 7 Feb 2022 12:13:17 -0800 +Subject: [PATCH 06/12] unused variable --- .../src/tensorflow_lite_support/cc/task/core/task_utils.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h -index 03ef9ade9af41..e95ea73a4a812 100644 +index 540d3c2e7c7d4..b9438a576ee5b 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h -@@ -144,8 +144,10 @@ inline absl::Status PopulateVector(const TfLiteTensor* tensor, +@@ -145,8 +145,10 @@ inline absl::Status PopulateVector(const TfLiteTensor* tensor, template <> inline absl::Status PopulateVector<std::string>( const TfLiteTensor* tensor, std::vector<std::string>* data) { @@ -25,5 +25,5 @@ data->reserve(num); for (int i = 0; i < num; i++) { -- -2.34.1.307.g9b7440fafd-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/patches/0007-do-not-use-absl-any.patch b/third_party/tflite_support/patches/0007-do-not-use-absl-any.patch index 0fbe740..a6281503 100644 --- a/third_party/tflite_support/patches/0007-do-not-use-absl-any.patch +++ b/third_party/tflite_support/patches/0007-do-not-use-absl-any.patch
@@ -1,7 +1,7 @@ -From d3d4385132632282fc91c735875ebfc90697b067 Mon Sep 17 00:00:00 2001 +From 6ccec4e3baea4b7c14dcf404c97c68634c912910 Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Thu, 16 Dec 2021 13:28:16 -0800 -Subject: [PATCH 07/11] do not use absl any +Date: Mon, 7 Feb 2022 12:13:34 -0800 +Subject: [PATCH 07/12] do not use absl any --- .../cc/task/vision/core/frame_buffer.h | 27 ------------------- @@ -60,5 +60,5 @@ Format format_; Orientation orientation_; -- -2.34.1.307.g9b7440fafd-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/patches/0008-unused-string-include.patch b/third_party/tflite_support/patches/0008-unused-string-include.patch index 2f5c20aeb..239b57506 100644 --- a/third_party/tflite_support/patches/0008-unused-string-include.patch +++ b/third_party/tflite_support/patches/0008-unused-string-include.patch
@@ -1,7 +1,7 @@ -From 5feffc2cdd8c970490fadd812401be4eb57174d5 Mon Sep 17 00:00:00 2001 +From 731c17145b6421250793e49c72d384edc49edce4 Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Thu, 16 Dec 2021 13:43:57 -0800 -Subject: [PATCH 08/11] unused string include +Date: Mon, 7 Feb 2022 12:13:50 -0800 +Subject: [PATCH 08/12] unused string include --- .../cc/text/tokenizers/tokenizer_jni_lib.h | 2 -- @@ -21,5 +21,5 @@ #include "tensorflow_lite_support/cc/utils/jni_utils.h" -- -2.34.1.307.g9b7440fafd-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/patches/0010-only-support-model-file-passed-in-from-mem.patch b/third_party/tflite_support/patches/0009-only-support-model-file-passed-in-from-mem.patch similarity index 98% rename from third_party/tflite_support/patches/0010-only-support-model-file-passed-in-from-mem.patch rename to third_party/tflite_support/patches/0009-only-support-model-file-passed-in-from-mem.patch index d97f8ed..2718e8fc 100644 --- a/third_party/tflite_support/patches/0010-only-support-model-file-passed-in-from-mem.patch +++ b/third_party/tflite_support/patches/0009-only-support-model-file-passed-in-from-mem.patch
@@ -1,7 +1,7 @@ -From 4b7e971e2f2f6ef3fd394858d975b64479047872 Mon Sep 17 00:00:00 2001 +From b5c9f0bb86abe933cada611e9d43f73280c5b227 Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Mon, 20 Dec 2021 08:50:35 -0800 -Subject: [PATCH 10/11] only support model file passed in from mem +Date: Mon, 7 Feb 2022 12:14:41 -0800 +Subject: [PATCH 09/12] only support model file passed in from mem --- .../cc/task/core/external_file_handler.cc | 143 ++---------------- @@ -261,5 +261,5 @@ #include "absl/memory/memory.h" // from @com_google_absl -- -2.34.1.307.g9b7440fafd-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/patches/0011-run-clang-format.patch b/third_party/tflite_support/patches/0010-run-clang-format.patch similarity index 95% rename from third_party/tflite_support/patches/0011-run-clang-format.patch rename to third_party/tflite_support/patches/0010-run-clang-format.patch index 6f390e38..fbc949f3 100644 --- a/third_party/tflite_support/patches/0011-run-clang-format.patch +++ b/third_party/tflite_support/patches/0010-run-clang-format.patch
@@ -1,7 +1,7 @@ -From 66d958947df0a4366b2a808e2a74e5ba412a2c38 Mon Sep 17 00:00:00 2001 +From 7cfcaacefdb45b518ac5808eebbffe6cc7131121 Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Mon, 20 Dec 2021 11:40:47 -0800 -Subject: [PATCH 11/11] run clang format +Date: Mon, 7 Feb 2022 12:20:58 -0800 +Subject: [PATCH 10/12] run clang format --- .../configuration/edgetpu_coral_plugin.cc | 20 +- @@ -18,13 +18,16 @@ .../c/task/text/nl_classifier.h | 3 +- .../c/task/vision/image_classifier.cc | 9 +- .../c/task/vision/image_classifier.h | 9 +- + .../c/task/vision/image_segmenter.h | 6 +- + .../c/task/vision/object_detector.cc | 6 +- .../c/task/vision/object_detector.h | 6 +- .../test/task/vision/image_classifier_test.cc | 84 +- + .../test/task/vision/object_detector_test.cc | 90 +- .../src/tensorflow_lite_support/cc/common.cc | 2 +- .../src/tensorflow_lite_support/cc/common.h | 5 +- .../cc/port/default/status_macros.h | 2 +- .../cc/port/default/statusor_internals.h | 38 +- - .../cc/port/default/tflite_wrapper.cc | 12 +- + .../cc/port/default/tflite_wrapper.cc | 9 +- .../cc/port/default/tflite_wrapper.h | 2 +- .../cc/port/integral_types.h | 2 +- .../cc/task/audio/audio_classifier.cc | 2 +- @@ -37,11 +40,10 @@ .../cc/task/core/error_reporter.cc | 8 +- .../cc/task/core/label_map_item.cc | 5 +- .../cc/task/core/label_map_item.h | 7 +- - .../cc/task/core/proto/external_file.proto | 2 - .../cc/task/core/score_calibration.cc | 8 +- .../cc/task/core/score_calibration.h | 11 +- .../cc/task/core/task_api_factory.h | 8 +- - .../cc/task/core/task_utils.h | 23 +- + .../cc/task/core/task_utils.h | 30 +- .../cc/task/core/tflite_engine.cc | 14 +- .../cc/task/core/tflite_engine.h | 13 +- .../cc/task/processor/audio_preprocessor.cc | 5 +- @@ -51,15 +53,17 @@ .../cc/task/processor/processor.h | 5 +- .../cc/task/processor/regex_preprocessor.cc | 3 +- .../cc/task/processor/regex_preprocessor.h | 3 +- - .../cc/task/text/bert_nl_classifier.cc | 7 +- + .../cc/task/text/bert_nl_classifier.cc | 3 +- .../cc/task/text/bert_nl_classifier.h | 2 +- .../cc/task/text/bert_question_answerer.cc | 34 +- .../cc/task/text/bert_question_answerer.h | 7 +- - .../task/text/nlclassifier/nl_classifier.cc | 16 +- - .../cc/task/text/nlclassifier/nl_classifier.h | 16 +- + .../task/text/nlclassifier/nl_classifier.cc | 18 +- + .../cc/task/text/nlclassifier/nl_classifier.h | 19 +- .../cc/task/text/question_answerer.h | 6 +- + .../cc/task/text/text_embedder.cc | 6 +- + .../cc/task/text/text_embedder.h | 3 +- .../text/universal_sentence_encoder_qa.cc | 14 +- - .../task/text/universal_sentence_encoder_qa.h | 9 +- + .../task/text/universal_sentence_encoder_qa.h | 7 +- .../task/vision/core/base_vision_task_api.h | 9 +- .../cc/task/vision/core/classification_head.h | 2 +- .../cc/task/vision/core/frame_buffer.h | 47 +- @@ -69,11 +73,10 @@ .../cc/task/vision/image_classifier.h | 8 +- .../cc/task/vision/image_embedder.cc | 17 +- .../cc/task/vision/image_embedder.h | 9 +- - .../cc/task/vision/image_segmenter.cc | 15 +- + .../cc/task/vision/image_segmenter.cc | 17 +- .../cc/task/vision/image_segmenter.h | 8 +- .../cc/task/vision/object_detector.cc | 16 +- .../cc/task/vision/object_detector.h | 5 +- - .../cc/task/vision/proto/segmentations.proto | 8 +- .../vision/utils/frame_buffer_common_utils.cc | 59 +- .../vision/utils/frame_buffer_common_utils.h | 37 +- .../task/vision/utils/frame_buffer_utils.cc | 50 +- @@ -88,7 +91,8 @@ .../test/task/text/bert_nl_classifier_test.cc | 36 +- .../task/text/bert_question_answerer_test.cc | 7 +- .../text/nlclassifier/nl_classifier_test.cc | 83 +- - .../test/task/vision/image_classifier_test.cc | 149 +- + .../cc/test/task/text/text_embedder_test.cc | 16 +- + .../test/task/vision/image_classifier_test.cc | 158 +- .../test/task/vision/image_embedder_test.cc | 95 +- .../test/task/vision/image_segmenter_test.cc | 117 +- .../test/task/vision/object_detector_test.cc | 157 +- @@ -141,7 +145,7 @@ .../text/desktop/bert_nl_classifier_demo.cc | 14 +- .../desktop/bert_question_answerer_demo.cc | 18 +- .../task/text/desktop/nl_classifier_demo.cc | 14 +- - .../universal_sentence_encoder_qa_demo.cc | 32 +- + .../universal_sentence_encoder_qa_demo.cc | 17 +- .../vision/desktop/image_classifier_demo.cc | 34 +- .../vision/desktop/image_embedder_demo.cc | 30 +- .../vision/desktop/image_segmenter_demo.cc | 24 +- @@ -149,40 +153,28 @@ .../task/vision/desktop/utils/image_utils.cc | 12 +- .../task/vision/desktop/utils/image_utils.h | 2 +- .../ios/sources/TFLCommon.h | 11 +- - .../ios/sources/TFLCommonUtils.h | 41 +- - .../ios/sources/TFLCommonUtils.m | 42 +- + .../ios/sources/TFLCommonUtils.h | 32 +- .../core/sources/TFLBaseOptions+Helpers.h | 2 +- - .../core/sources/TFLBaseOptions+Helpers.m | 2 +- .../ios/task/core/sources/TFLBaseOptions.h | 32 +- - .../ios/task/core/sources/TFLBaseOptions.m | 16 +- + .../processor/sources/TFLCategory+Helpers.h | 2 +- + .../ios/task/processor/sources/TFLCategory.h | 8 +- .../TFLClassificationOptions+Helpers.h | 6 +- - .../TFLClassificationOptions+Helpers.m | 66 +- .../sources/TFLClassificationOptions.h | 9 +- - .../sources/TFLClassificationOptions.m | 5 +- - .../sources/TFLClassificationResult.h | 23 +- - .../utils/sources/TFLClassificationUtils.h | 21 +- - .../utils/sources/TFLClassificationUtils.m | 31 +- + .../sources/TFLClassificationResult+Helpers.h | 17 +- + .../sources/TFLClassificationResult.h | 15 +- + .../sources/TFLDetectionResult+Helpers.h | 12 +- + .../processor/sources/TFLDetectionResult.h | 15 +- .../Sources/TFLBertNLClassifier.h | 21 +- - .../Sources/TFLBertNLClassifier.m | 28 +- .../nlclassifier/Sources/TFLNLClassifier.h | 47 +- - .../nlclassifier/Sources/TFLNLClassifier.m | 18 +- - .../Tests/TFLBertNLClassifierTest.m | 29 +- - .../nlclassifier/Tests/TFLNLClassifierTest.m | 28 +- .../text/qa/Sources/TFLBertQuestionAnswerer.h | 4 +- - .../text/qa/Sources/TFLBertQuestionAnswerer.m | 23 +- - .../qa/Tests/TFLBertQuestionAnswererTest.m | 33 +- .../task/vision/sources/TFLImageClassifier.h | 37 +- - .../task/vision/sources/TFLImageClassifier.m | 52 +- + .../task/vision/sources/TFLObjectDetector.h | 36 +- .../task/vision/utils/sources/GMLImageUtils.h | 5 +- - .../task/vision/utils/sources/GMLImageUtils.m | 146 +- - .../TFLImageClassifierTests.m | 109 +- + .../vision/utils/sources/GMLImage+Helpers.h | 6 +- .../tokenizers/Sources/TFLBertTokenizer.h | 6 +- - .../tokenizers/Sources/TFLBertTokenizer.mm | 10 +- .../Sources/TFLSentencepieceTokenizer.h | 2 +- - .../Sources/TFLSentencepieceTokenizer.mm | 12 +- .../text/tokenizers/Sources/TFLTokenizer.h | 4 +- .../tokenizers/Sources/TFLTokenizerUtil.h | 11 +- - .../tokenizers/Sources/TFLTokenizerUtil.mm | 15 +- .../lite/support/audio/TensorAudio.java | 524 ++--- .../lite/support/common/FileUtil.java | 301 +-- .../lite/support/common/Operator.java | 15 +- @@ -217,7 +209,7 @@ .../lite/support/label/TensorLabel.java | 331 +-- .../lite/support/label/ops/LabelAxisOp.java | 70 +- .../lite/support/model/GpuDelegateProxy.java | 71 +- - .../tensorflow/lite/support/model/Model.java | 449 ++-- + .../tensorflow/lite/support/model/Model.java | 467 +++-- .../support/tensorbuffer/TensorBuffer.java | 899 ++++---- .../tensorbuffer/TensorBufferFloat.java | 181 +- .../tensorbuffer/TensorBufferUint8.java | 188 +- @@ -288,7 +280,7 @@ .../metadata/cc/metadata_extractor.cc | 21 +- .../metadata/cc/metadata_extractor.h | 4 +- .../metadata/cc/metadata_populator.h | 7 +- - .../metadata/cc/metadata_version.cc | 35 +- + .../metadata/cc/metadata_version.cc | 37 +- .../flatbuffers_lib/flatbuffers_lib.cc | 2 +- .../support/metadata/BoundedInputStream.java | 138 +- .../support/metadata/ByteBufferChannel.java | 188 +- @@ -305,8 +297,6 @@ .../support/metadata/MetadataParserTest.java | 18 +- .../lite/support/metadata/ZipFileTest.java | 206 +- .../odml/ios/image/apis/GMLImage.h | 47 +- - .../odml/ios/image/sources/GMLImage.m | 2 +- - .../odml/ios/image/tests/GMLImageTests.m | 73 +- .../android/odml/image/BitmapExtractor.java | 43 +- .../odml/image/BitmapImageContainer.java | 70 +- .../odml/image/BitmapMlImageBuilder.java | 137 +- @@ -326,9 +316,15 @@ .../odml/image/MediaImageExtractorTest.java | 48 +- .../odml/image/MediaMlImageBuilderTest.java | 109 +- .../android/odml/image/TestImageCreator.java | 211 +- + .../tools/ci_build/common.sh | 143 +- + .../pip_package/rpi/build_arm_pip_package.sh | 49 +- + .../tools/pip_package/rpi/install_bazel.sh | 75 +- .../src/third_party/fft2d/fft.h | 12 +- .../src/third_party/fft2d/fft2d.h | 12 +- - 324 files changed, 17479 insertions(+), 17052 deletions(-) + .../com_google_protobuf_build.patch | 12 +- + 318 files changed, 17318 insertions(+), 16946 deletions(-) + mode change 100755 => 100644 third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh + mode change 100755 => 100644 third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh diff --git a/third_party/tflite_support/src/tensorflow_lite_support/acceleration/configuration/edgetpu_coral_plugin.cc b/third_party/tflite_support/src/tensorflow_lite_support/acceleration/configuration/edgetpu_coral_plugin.cc index 9f27f3baae82f..6a16d12856258 100644 @@ -570,10 +566,10 @@ // Invokes the encapsulated TFLite model and classifies the input text. Categories* TfLiteNLClassifierClassify(const TfLiteNLClassifier* classifier, diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_classifier.cc b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_classifier.cc -index edf3889059b27..8981e66b41d0c 100644 +index 7c81bc4537c00..b3517ad7344e9 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_classifier.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_classifier.cc -@@ -108,7 +108,8 @@ TfLiteImageClassifierOptions TfLiteImageClassifierOptionsCreate() { +@@ -110,7 +110,8 @@ TfLiteImageClassifierOptions TfLiteImageClassifierOptionsCreate() { } TfLiteImageClassifier* TfLiteImageClassifierFromOptions( @@ -583,7 +579,7 @@ StatusOr<ImageClassifierOptionsCpp> cpp_option_status = CreateImageClassifierCppOptionsFromCOptions(options); -@@ -175,7 +176,8 @@ TfLiteClassificationResult* GetClassificationResultCStruct( +@@ -177,7 +178,8 @@ TfLiteClassificationResult* GetClassificationResultCStruct( TfLiteClassificationResult* TfLiteImageClassifierClassifyWithRoi( const TfLiteImageClassifier* classifier, @@ -593,7 +589,7 @@ TfLiteSupportError** error) { if (classifier == nullptr) { tflite::support::CreateTfLiteSupportError( -@@ -219,7 +221,8 @@ TfLiteClassificationResult* TfLiteImageClassifierClassifyWithRoi( +@@ -220,7 +222,8 @@ TfLiteClassificationResult* TfLiteImageClassifierClassifyWithRoi( TfLiteClassificationResult* TfLiteImageClassifierClassify( const TfLiteImageClassifier* classifier, @@ -637,8 +633,56 @@ TfLiteSupportError** error); // Disposes off the image classifier. +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_segmenter.h b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_segmenter.h +index 5c2becc010e28..23b6b6eeb994c 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_segmenter.h ++++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_segmenter.h +@@ -171,7 +171,8 @@ TfLiteImageSegmenterOptions TfLiteImageSegmenterOptionsCreate(); + // TfLiteSupportErrorDelete(error) + // + TfLiteImageSegmenter* TfLiteImageSegmenterFromOptions( +- const TfLiteImageSegmenterOptions* options, TfLiteSupportError** error); ++ const TfLiteImageSegmenterOptions* options, ++ TfLiteSupportError** error); + + // Invokes the encapsulated TFLite model and performs image segmentation on + // the frame_buffer. +@@ -200,7 +201,8 @@ TfLiteImageSegmenter* TfLiteImageSegmenterFromOptions( + // + TfLiteSegmentationResult* TfLiteImageSegmenterSegment( + const TfLiteImageSegmenter* segmenter, +- const TfLiteFrameBuffer* frame_buffer, TfLiteSupportError** error); ++ const TfLiteFrameBuffer* frame_buffer, ++ TfLiteSupportError** error); + + // Disposes of the image segmenter. + void TfLiteImageSegmenterDelete(TfLiteImageSegmenter* segmenter); +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.cc b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.cc +index 46846a05ed2d7..90af0ac369c5d 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.cc ++++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.cc +@@ -109,7 +109,8 @@ TfLiteObjectDetectorOptions TfLiteObjectDetectorOptionsCreate() { + } + + TfLiteObjectDetector* TfLiteObjectDetectorFromOptions( +- const TfLiteObjectDetectorOptions* options, TfLiteSupportError** error) { ++ const TfLiteObjectDetectorOptions* options, ++ TfLiteSupportError** error) { + StatusOr<ObjectDetectorOptionsCpp> cpp_option_status = + CreateObjectDetectorCppOptionsFromCOptions(options); + +@@ -174,7 +175,8 @@ TfLiteDetectionResult* GetDetectionResultCStruct( + } + + TfLiteDetectionResult* TfLiteObjectDetectorDetect( +- const TfLiteObjectDetector* detector, const TfLiteFrameBuffer* frame_buffer, ++ const TfLiteObjectDetector* detector, ++ const TfLiteFrameBuffer* frame_buffer, + TfLiteSupportError** error) { + if (detector == nullptr) { + tflite::support::CreateTfLiteSupportError( diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.h b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.h -index a46cf043aeb24..5a2d3e1d1e4d2 100644 +index 5c74a1131df1c..b31116eeb44ee 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.h @@ -157,7 +157,8 @@ TfLiteObjectDetectorOptions TfLiteObjectDetectorOptionsCreate(); @@ -900,6 +944,279 @@ ASSERT_NE(classification_result, nullptr); EXPECT_GE(classification_result->size, 1); +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/test/task/vision/object_detector_test.cc b/third_party/tflite_support/src/tensorflow_lite_support/c/test/task/vision/object_detector_test.cc +index f52623ada454c..99cd0034287ad 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/c/test/task/vision/object_detector_test.cc ++++ b/third_party/tflite_support/src/tensorflow_lite_support/c/test/task/vision/object_detector_test.cc +@@ -46,8 +46,8 @@ constexpr char kMobileSsdWithMetadata[] = + "coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.tflite"; + + StatusOr<ImageData> LoadImage(const char* image_name) { +- return DecodeImageFromFile(JoinPath("./" /*test src dir*/, +- kTestDataDirectory, image_name)); ++ return DecodeImageFromFile( ++ JoinPath("./" /*test src dir*/, kTestDataDirectory, image_name)); + } + + void VerifyDetection(const TfLiteDetection& detection, +@@ -96,7 +96,8 @@ TEST_F(ObjectDetectorFromOptionsTest, FailsWithNullOptionsAndError) { + TfLiteObjectDetectorFromOptions(nullptr, &error); + + EXPECT_EQ(object_detector, nullptr); +- if (object_detector) TfLiteObjectDetectorDelete(object_detector); ++ if (object_detector) ++ TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); +@@ -111,7 +112,8 @@ TEST_F(ObjectDetectorFromOptionsTest, FailsWithMissingModelPath) { + TfLiteObjectDetector* object_detector = + TfLiteObjectDetectorFromOptions(&options, nullptr); + EXPECT_EQ(object_detector, nullptr); +- if (object_detector) TfLiteObjectDetectorDelete(object_detector); ++ if (object_detector) ++ TfLiteObjectDetectorDelete(object_detector); + } + + TEST_F(ObjectDetectorFromOptionsTest, FailsWithMissingModelPathAndError) { +@@ -122,7 +124,8 @@ TEST_F(ObjectDetectorFromOptionsTest, FailsWithMissingModelPathAndError) { + TfLiteObjectDetectorFromOptions(&options, &error); + + EXPECT_EQ(object_detector, nullptr); +- if (object_detector) TfLiteObjectDetectorDelete(object_detector); ++ if (object_detector) ++ TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); +@@ -133,8 +136,8 @@ TEST_F(ObjectDetectorFromOptionsTest, FailsWithMissingModelPathAndError) { + } + + TEST_F(ObjectDetectorFromOptionsTest, SucceedsWithModelPath) { +- std::string model_path = JoinPath("./" /*test src dir*/, +- kTestDataDirectory, kMobileSsdWithMetadata); ++ std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, ++ kMobileSsdWithMetadata); + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); + TfLiteObjectDetector* object_detector = +@@ -145,8 +148,8 @@ TEST_F(ObjectDetectorFromOptionsTest, SucceedsWithModelPath) { + } + + TEST_F(ObjectDetectorFromOptionsTest, SucceedsWithNumberOfThreadsAndError) { +- std::string model_path = JoinPath("./" /*test src dir*/, +- kTestDataDirectory, kMobileSsdWithMetadata); ++ std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, ++ kMobileSsdWithMetadata); + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); + options.base_options.compute_settings.cpu_settings.num_threads = 3; +@@ -158,14 +161,16 @@ TEST_F(ObjectDetectorFromOptionsTest, SucceedsWithNumberOfThreadsAndError) { + EXPECT_NE(object_detector, nullptr); + EXPECT_EQ(error, nullptr); + +- if (object_detector) TfLiteObjectDetectorDelete(object_detector); +- if (error) TfLiteSupportErrorDelete(error); ++ if (object_detector) ++ TfLiteObjectDetectorDelete(object_detector); ++ if (error) ++ TfLiteSupportErrorDelete(error); + } + + TEST_F(ObjectDetectorFromOptionsTest, + FailsWithClassNameDenyListAndClassNameAllowListAndError) { +- std::string model_path = JoinPath("./" /*test src dir*/, +- kTestDataDirectory, kMobileSsdWithMetadata); ++ std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, ++ kMobileSsdWithMetadata); + + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); +@@ -183,7 +188,8 @@ TEST_F(ObjectDetectorFromOptionsTest, + TfLiteObjectDetectorFromOptions(&options, &error); + + EXPECT_EQ(object_detector, nullptr); +- if (object_detector) TfLiteObjectDetectorDelete(object_detector); ++ if (object_detector) ++ TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); +@@ -195,7 +201,8 @@ TEST_F(ObjectDetectorFromOptionsTest, + + TEST(ObjectDetectorNullDetectorDetectTest, + FailsWithNullObjectDetectorAndError) { +- SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, LoadImage("cats_and_dogs.jpg")); ++ SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, ++ LoadImage("cats_and_dogs.jpg")); + + TfLiteSupportError* error = nullptr; + TfLiteDetectionResult* detection_result = +@@ -204,7 +211,8 @@ TEST(ObjectDetectorNullDetectorDetectTest, + ImageDataFree(&image_data); + + EXPECT_EQ(detection_result, nullptr); +- if (detection_result) TfLiteDetectionResultDelete(detection_result); ++ if (detection_result) ++ TfLiteDetectionResultDelete(detection_result); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); +@@ -217,9 +225,8 @@ TEST(ObjectDetectorNullDetectorDetectTest, + class ObjectDetectorDetectTest : public tflite_shims::testing::Test { + protected: + void SetUp() override { +- std::string model_path = +- JoinPath("./" /*test src dir*/, kTestDataDirectory, +- kMobileSsdWithMetadata); ++ std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, ++ kMobileSsdWithMetadata); + + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); +@@ -232,7 +239,8 @@ class ObjectDetectorDetectTest : public tflite_shims::testing::Test { + }; + + TEST_F(ObjectDetectorDetectTest, SucceedsWithImageData) { +- SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, LoadImage("cats_and_dogs.jpg")); ++ SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, ++ LoadImage("cats_and_dogs.jpg")); + + TfLiteFrameBuffer frame_buffer = { + .format = kRGB, +@@ -251,7 +259,8 @@ TEST_F(ObjectDetectorDetectTest, SucceedsWithImageData) { + } + + TEST_F(ObjectDetectorDetectTest, FailsWithNullFrameBufferAndError) { +- SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, LoadImage("cats_and_dogs.jpg")); ++ SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, ++ LoadImage("cats_and_dogs.jpg")); + + TfLiteSupportError* error = nullptr; + TfLiteDetectionResult* detection_result = +@@ -260,7 +269,8 @@ TEST_F(ObjectDetectorDetectTest, FailsWithNullFrameBufferAndError) { + ImageDataFree(&image_data); + + EXPECT_EQ(detection_result, nullptr); +- if (detection_result) TfLiteDetectionResultDelete(detection_result); ++ if (detection_result) ++ TfLiteDetectionResultDelete(detection_result); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); +@@ -271,7 +281,8 @@ TEST_F(ObjectDetectorDetectTest, FailsWithNullFrameBufferAndError) { + } + + TEST_F(ObjectDetectorDetectTest, FailsWithNullImageDataAndError) { +- SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, LoadImage("cats_and_dogs.jpg")); ++ SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, ++ LoadImage("cats_and_dogs.jpg")); + TfLiteSupportError* error = nullptr; + TfLiteDetectionResult* detection_result = + TfLiteObjectDetectorDetect(object_detector, nullptr, &error); +@@ -279,7 +290,8 @@ TEST_F(ObjectDetectorDetectTest, FailsWithNullImageDataAndError) { + ImageDataFree(&image_data); + + EXPECT_EQ(detection_result, nullptr); +- if (detection_result) TfLiteDetectionResultDelete(detection_result); ++ if (detection_result) ++ TfLiteDetectionResultDelete(detection_result); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); +@@ -292,8 +304,8 @@ TEST_F(ObjectDetectorDetectTest, FailsWithNullImageDataAndError) { + TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + SucceedsWithClassNameDenyList) { + char* denylisted_label_name = (char*)"cat"; +- std::string model_path = JoinPath("./" /*test src dir*/, +- kTestDataDirectory, kMobileSsdWithMetadata); ++ std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, ++ kMobileSsdWithMetadata); + + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); +@@ -306,7 +318,8 @@ TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + TfLiteObjectDetectorFromOptions(&options, nullptr); + ASSERT_NE(object_detector, nullptr); + +- SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, LoadImage("cats_and_dogs.jpg")); ++ SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, ++ LoadImage("cats_and_dogs.jpg")); + + TfLiteFrameBuffer frame_buffer = { + .format = kRGB, +@@ -318,7 +331,8 @@ TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + TfLiteObjectDetectorDetect(object_detector, &frame_buffer, nullptr); + + ImageDataFree(&image_data); +- if (object_detector) TfLiteObjectDetectorDelete(object_detector); ++ if (object_detector) ++ TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(detection_result, nullptr); + EXPECT_GE(detection_result->size, 1); +@@ -334,8 +348,8 @@ TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + SucceedsWithClassNameAllowList) { + char* allowlisted_label_name = (char*)"cat"; +- std::string model_path = JoinPath("./" /*test src dir*/, +- kTestDataDirectory, kMobileSsdWithMetadata) ++ std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, ++ kMobileSsdWithMetadata) + .data(); + + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); +@@ -349,7 +363,8 @@ TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + TfLiteObjectDetectorFromOptions(&options, nullptr); + ASSERT_NE(object_detector, nullptr); + +- SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, LoadImage("cats_and_dogs.jpg")); ++ SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, ++ LoadImage("cats_and_dogs.jpg")); + + TfLiteFrameBuffer frame_buffer = { + .format = kRGB, +@@ -361,7 +376,8 @@ TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + TfLiteObjectDetectorDetect(object_detector, &frame_buffer, nullptr); + + ImageDataFree(&image_data); +- if (object_detector) TfLiteObjectDetectorDelete(object_detector); ++ if (object_detector) ++ TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(detection_result, nullptr); + EXPECT_GE(detection_result->size, 1); +@@ -376,8 +392,8 @@ TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + + TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + SucceedsWithScoreThreshold) { +- std::string model_path = JoinPath("./" /*test src dir*/, +- kTestDataDirectory, kMobileSsdWithMetadata) ++ std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, ++ kMobileSsdWithMetadata) + .data(); + + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); +@@ -389,7 +405,8 @@ TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + TfLiteObjectDetectorFromOptions(&options, nullptr); + ASSERT_NE(object_detector, nullptr); + +- SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, LoadImage("cats_and_dogs.jpg")); ++ SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, ++ LoadImage("cats_and_dogs.jpg")); + + TfLiteFrameBuffer frame_buffer = { + .format = kRGB, +@@ -401,7 +418,8 @@ TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + TfLiteObjectDetectorDetect(object_detector, &frame_buffer, nullptr); + + ImageDataFree(&image_data); +- if (object_detector) TfLiteObjectDetectorDelete(object_detector); ++ if (object_detector) ++ TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(detection_result, nullptr); + EXPECT_EQ(detection_result->size, 1); diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/common.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/common.cc index abfef722d6659..09e9a83e07bef 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/common.cc @@ -1061,7 +1378,7 @@ MoveAssignBase() = default; MoveAssignBase(const MoveAssignBase&) = default; diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.cc -index 6334c02d738a6..0b3e5d6a2269a 100644 +index d47c1ce7e5179..bb43d09f4a96b 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.cc @@ -15,7 +15,7 @@ limitations under the License. @@ -1073,17 +1390,7 @@ #include "absl/strings/str_format.h" // from @com_google_absl #include "tensorflow/lite/c/common.h" #include "tensorflow/lite/delegates/interpreter_utils.h" -@@ -53,7 +53,8 @@ TfLiteInterpreterWrapper::TfLiteInterpreterWrapper( - : delegate_(nullptr, nullptr), - got_error_do_not_delegate_anymore_(false), - default_model_namespace_(default_model_namespace), -- default_model_id_(default_model_id), mini_benchmark_(nullptr) {} -+ default_model_id_(default_model_id), -+ mini_benchmark_(nullptr) {} - - std::string TfLiteInterpreterWrapper::ModelNamespace() { - const auto& ns_from_acceleration = -@@ -299,7 +300,9 @@ absl::Status TfLiteInterpreterWrapper::InvokeWithoutFallback() { +@@ -304,7 +304,9 @@ absl::Status TfLiteInterpreterWrapper::InvokeWithoutFallback() { return absl::OkStatus(); } @@ -1094,7 +1401,7 @@ void TfLiteInterpreterWrapper::SetTfLiteCancellation() { // Create a cancellation check function and set to the TFLite interpreter. -@@ -312,7 +315,8 @@ void TfLiteInterpreterWrapper::SetTfLiteCancellation() { +@@ -317,7 +319,8 @@ void TfLiteInterpreterWrapper::SetTfLiteCancellation() { } absl::Status TfLiteInterpreterWrapper::LoadDelegatePlugin( @@ -1105,7 +1412,7 @@ absl::StrFormat("%sPlugin", name), tflite_settings); diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.h -index 278ae7643264e..9f32fa8735ccf 100644 +index 9a6fdebd99903..a9deed9f93521 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.h @@ -19,7 +19,7 @@ limitations under the License. @@ -1366,23 +1673,6 @@ // A class that represents a hierarchy of labels as specified in a label map. // -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/external_file.proto b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/external_file.proto -index c0a42124e1b50..91b6a214b1253 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/external_file.proto -+++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/external_file.proto -@@ -17,7 +17,6 @@ syntax = "proto2"; - - package tflite.task.core; - -- - // Represents external files used by the Task APIs (e.g. TF Lite FlatBuffer or - // plain-text labels file). The files can be specified by one of the following - // three ways: -@@ -64,4 +63,3 @@ message FileDescriptorMeta { - // offset of a given asset obtained from AssetFileDescriptor#getStartOffset(). - optional int64 offset = 3; - } -- diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/score_calibration.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/score_calibration.cc index 818839a77e43d..e7faebad487b9 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/score_calibration.cc @@ -1433,7 +1723,7 @@ : label(label), slope(slope), diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_api_factory.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_api_factory.h -index 4e4b42cceaff7..f42d703fd1ae8 100644 +index 3d3bc801a6e5d..bbe549a802b39 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_api_factory.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_api_factory.h @@ -18,7 +18,7 @@ limitations under the License. @@ -1455,7 +1745,7 @@ std::unique_ptr<tflite::OpResolver> resolver = absl::make_unique<tflite_shims::ops::builtin::BuiltinOpResolver>(), int num_threads = 1, -@@ -151,7 +152,8 @@ class TaskAPIFactory { +@@ -156,7 +157,8 @@ class TaskAPIFactory { private: template <typename T, EnableIfBaseUntypedTaskApiSubclass<T> = nullptr> static tflite::support::StatusOr<std::unique_ptr<T>> CreateFromTfLiteEngine( @@ -1466,23 +1756,28 @@ tflite::proto::ComputeSettings()) { tflite::proto::ComputeSettings settings_copy = diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h -index e95ea73a4a812..7cde474dcd8f6 100644 +index b9438a576ee5b..43a508ae4d410 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h -@@ -21,9 +21,9 @@ limitations under the License. +@@ -21,12 +21,12 @@ limitations under the License. #include <numeric> #include <vector> -#include "absl/memory/memory.h" // from @com_google_absl -#include "absl/status/status.h" // from @com_google_absl -#include "absl/strings/str_cat.h" // from @com_google_absl -+#include "absl/memory/memory.h" // from @com_google_absl -+#include "absl/status/status.h" // from @com_google_absl -+#include "absl/strings/str_cat.h" // from @com_google_absl - #include "absl/strings/str_format.h" // from @com_google_absl - #include "flatbuffers/flatbuffers.h" // from @flatbuffers +-#include "absl/strings/str_format.h" // from @com_google_absl ++#include "absl/memory/memory.h" // from @com_google_absl ++#include "absl/status/status.h" // from @com_google_absl ++#include "absl/strings/str_cat.h" // from @com_google_absl ++#include "absl/strings/str_format.h" // from @com_google_absl + #include "absl/strings/string_view.h" // from @com_google_absl +-#include "flatbuffers/flatbuffers.h" // from @flatbuffers ++#include "flatbuffers/flatbuffers.h" // from @flatbuffers #include "tensorflow/lite/kernels/internal/tensor_ctypes.h" -@@ -65,9 +65,11 @@ tflite::support::StatusOr<T*> AssertAndReturnTypedTensor( + #include "tensorflow/lite/kernels/op_macros.h" + #include "tensorflow/lite/string_util.h" +@@ -66,9 +66,11 @@ tflite::support::StatusOr<T*> AssertAndReturnTypedTensor( // type or has not the same number of elements. // Note: std::negation is not used because it is from C++17, where the code will // be compiled using C++14 in OSS. @@ -1497,7 +1792,7 @@ TfLiteTensor* tensor) { T* v; ASSIGN_OR_RETURN(v, AssertAndReturnTypedTensor<T>(tensor)); -@@ -92,7 +94,8 @@ inline absl::Status PopulateTensor(const std::vector<T>& data, +@@ -93,7 +95,8 @@ inline absl::Status PopulateTensor(const std::vector<T>& data, template <> inline absl::Status PopulateTensor<std::string>( @@ -1507,7 +1802,7 @@ if (tensor->type != kTfLiteString) { return tflite::support::CreateStatusWithPayload( absl::StatusCode::kInternal, -@@ -143,7 +146,8 @@ inline absl::Status PopulateVector(const TfLiteTensor* tensor, +@@ -144,7 +147,8 @@ inline absl::Status PopulateVector(const TfLiteTensor* tensor, template <> inline absl::Status PopulateVector<std::string>( @@ -1517,7 +1812,7 @@ if (tensor->type != typeToTfLiteType<std::string>()) { return absl::InvalidArgumentError("not of type string"); } -@@ -161,7 +165,8 @@ inline absl::Status PopulateVector<std::string>( +@@ -162,7 +166,8 @@ inline absl::Status PopulateVector<std::string>( // Note: std::negation is not used because it is from C++17, where the code will // be compiled using C++14 in OSS. template < @@ -1527,6 +1822,16 @@ typename = std::enable_if_t<std::is_same<T, std::string>::value == false>> inline absl::Status PopulateVectorToRepeated(const TfLiteTensor* tensor, TRepeatedField* data) { +@@ -238,7 +243,8 @@ int FindTensorIndexByName( + if (tensor_metadata != nullptr && tensor_metadata->size() == tensors.size()) { + int index = + FindTensorIndexByMetadataName(tensor_metadata, metadata_tensor_name); +- if (index > -1) return index; ++ if (index > -1) ++ return index; + } + + return FindTensorIndexByModelName(tensors, model_tensor_name); diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/tflite_engine.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/tflite_engine.cc index 484b9a099ecdc..0b34bad4f18f7 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/tflite_engine.cc @@ -1672,10 +1977,10 @@ ASSIGN_OR_RETURN(auto processor, Processor::Create<ClassificationPostprocessor>( diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/embedding_postprocessor.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/embedding_postprocessor.h -index fdc872a23d3d4..78cef8ab57e3d 100644 +index 7863e3aa82fb7..f04048d84b4ce 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/embedding_postprocessor.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/embedding_postprocessor.h -@@ -66,8 +66,8 @@ class EmbeddingPostprocessor : public Postprocessor { +@@ -69,8 +69,8 @@ class EmbeddingPostprocessor : public Postprocessor { // Performs actual cosine similarity computation. template <typename T> @@ -1686,7 +1991,7 @@ template <typename T> void NormalizeFeatureVector(T* feature_vector) const; -@@ -143,7 +143,8 @@ void EmbeddingPostprocessor::QuantizeFeatureVector(T* feature_vector) const { +@@ -146,7 +146,8 @@ void EmbeddingPostprocessor::QuantizeFeatureVector(T* feature_vector) const { /* static */ template <typename T> tflite::support::StatusOr<double> @@ -1696,7 +2001,7 @@ int num_elements) { if (num_elements <= 0) { return CreateStatusWithPayload( -@@ -171,7 +172,8 @@ EmbeddingPostprocessor::ComputeCosineSimilarity(const T* u, const T* v, +@@ -174,7 +175,8 @@ EmbeddingPostprocessor::ComputeCosineSimilarity(const T* u, const T* v, /* static */ template <typename T> tflite::support::StatusOr<double> EmbeddingPostprocessor::CosineSimilarity( @@ -1782,32 +2087,21 @@ absl::Status Preprocess(const std::string& text); diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.cc -index c52f73be8b7a8..ac8fa548c669d 100644 +index 386cb14c1a8c8..7de37f1082212 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.cc -@@ -23,8 +23,8 @@ limitations under the License. - #include <utility> - #include <vector> - --#include "absl/status/status.h" // from @com_google_absl --#include "absl/strings/ascii.h" // from @com_google_absl -+#include "absl/status/status.h" // from @com_google_absl -+#include "absl/strings/ascii.h" // from @com_google_absl - #include "absl/strings/str_format.h" // from @com_google_absl - #include "tensorflow/lite/c/common.h" - #include "tensorflow/lite/core/api/op_resolver.h" -@@ -76,7 +76,8 @@ int GetLastDimSize(const TfLiteTensor* tensor) { +@@ -56,7 +56,8 @@ absl::Status SanityCheckOptions(const BertNLClassifierOptions& options) { } // namespace absl::Status BertNLClassifier::Preprocess( - const std::vector<TfLiteTensor*>& input_tensors, const std::string& input) { + const std::vector<TfLiteTensor*>& input_tensors, + const std::string& input) { - auto* input_tensor_metadatas = - GetMetadataExtractor()->GetInputTensorMetadata(); - auto* ids_tensor = + return preprocessor_->Preprocess(input); + } + diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.h -index 541b5561d5c6d..91bcfe50712d0 100644 +index 4151025df917b..bcc9c5a533a3f 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.h @@ -22,7 +22,7 @@ limitations under the License. @@ -1946,10 +2240,10 @@ // Initialize the API with the tokenizer set in the metadata. absl::Status InitializeFromMetadata( diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.cc -index d3697f326db1b..6986bcc665733 100644 +index d03296d2d09b5..542d153cb1262 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.cc -@@ -22,8 +22,8 @@ limitations under the License. +@@ -22,10 +22,10 @@ limitations under the License. #include <vector> #include "absl/algorithm/container.h" // from @com_google_absl @@ -1958,19 +2252,22 @@ +#include "absl/status/status.h" // from @com_google_absl +#include "absl/strings/str_cat.h" // from @com_google_absl #include "absl/strings/string_view.h" // from @com_google_absl - #include "flatbuffers/flatbuffers.h" // from @flatbuffers +-#include "flatbuffers/flatbuffers.h" // from @flatbuffers ++#include "flatbuffers/flatbuffers.h" // from @flatbuffers #include "tensorflow/lite/c/common.h" -@@ -200,7 +200,8 @@ std::vector<Category> NLClassifier::Classify(const std::string& text) { + #include "tensorflow/lite/core/api/op_resolver.h" + #include "tensorflow/lite/kernels/internal/tensor_ctypes.h" +@@ -120,7 +120,8 @@ std::vector<Category> NLClassifier::Classify(const std::string& text) { } absl::Status NLClassifier::Preprocess( - const std::vector<TfLiteTensor*>& input_tensors, const std::string& input) { + const std::vector<TfLiteTensor*>& input_tensors, + const std::string& input) { - TfLiteTensor* input_tensor = FindTensorWithNameOrIndex( - input_tensors, GetMetadataExtractor()->GetInputTensorMetadata(), - struct_options_.input_tensor_name, struct_options_.input_tensor_index); -@@ -446,7 +447,8 @@ StatusOr<std::unique_ptr<NLClassifier>> NLClassifier::CreateFromOptions( + return preprocessor_->Preprocess(input); + } + +@@ -300,7 +301,8 @@ StatusOr<std::unique_ptr<NLClassifier>> NLClassifier::CreateFromOptions( StatusOr<std::unique_ptr<NLClassifier>> NLClassifier::CreateFromBufferAndOptions( @@ -1980,7 +2277,7 @@ const NLClassifierOptions& options, std::unique_ptr<tflite::OpResolver> resolver) { std::unique_ptr<NLClassifier> nl_classifier; -@@ -459,7 +461,8 @@ NLClassifier::CreateFromBufferAndOptions( +@@ -313,7 +315,8 @@ NLClassifier::CreateFromBufferAndOptions( } StatusOr<std::unique_ptr<NLClassifier>> NLClassifier::CreateFromFileAndOptions( @@ -1990,7 +2287,7 @@ std::unique_ptr<tflite::OpResolver> resolver) { std::unique_ptr<NLClassifier> nl_classifier; ASSIGN_OR_RETURN(nl_classifier, -@@ -470,7 +473,8 @@ StatusOr<std::unique_ptr<NLClassifier>> NLClassifier::CreateFromFileAndOptions( +@@ -324,7 +327,8 @@ StatusOr<std::unique_ptr<NLClassifier>> NLClassifier::CreateFromFileAndOptions( } StatusOr<std::unique_ptr<NLClassifier>> NLClassifier::CreateFromFdAndOptions( @@ -2001,7 +2298,7 @@ std::unique_ptr<NLClassifier> nl_classifier; ASSIGN_OR_RETURN(nl_classifier, diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h -index 2adafba8f2fa9..331a6e4274342 100644 +index ab5126348f380..30fa25044e1cf 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h @@ -23,8 +23,8 @@ limitations under the License. @@ -2052,6 +2349,16 @@ - const std::string& name, int index) { + const std::string& name, + int index) { + int tensor_index = FindTensorIndex(tensors, metadata_array, name, index); + return tensor_index >= 0 && tensor_index < tensors.size() + ? tensors[tensor_index] +@@ -192,7 +196,8 @@ class NLClassifier : public core::BaseTaskApi<std::vector<core::Category>, + const std::vector<TensorType*>& tensors, + const flatbuffers::Vector<flatbuffers::Offset<TensorMetadata>>* + metadata_array, +- const std::string& name, int default_index) { ++ const std::string& name, ++ int default_index) { if (metadata_array != nullptr && metadata_array->size() == tensors.size()) { for (size_t i = 0; i < metadata_array->size(); i++) { if (strcmp(name.data(), metadata_array->Get(i)->name()->c_str()) == 0) { @@ -2072,11 +2379,49 @@ public: explicit QuestionAnswerer(std::unique_ptr<core::TfLiteEngine> engine) : BaseTaskApi(std::move(engine)) {} +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.cc +index 6aef346971db5..e610790508423 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.cc ++++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.cc +@@ -49,7 +49,8 @@ absl::Status SanityCheckOptions(const TextEmbedderOptions& options) { + + /* static */ + tflite::support::StatusOr<double> TextEmbedder::CosineSimilarity( +- const FeatureVector& u, const FeatureVector& v) { ++ const FeatureVector& u, ++ const FeatureVector& v) { + return processor::EmbeddingPostprocessor::CosineSimilarity(u, v); + } + +@@ -133,7 +134,8 @@ tflite::support::StatusOr<EmbeddingResult> TextEmbedder::Embed( + } + + absl::Status TextEmbedder::Preprocess( +- const std::vector<TfLiteTensor*>& input_tensors, const std::string& input) { ++ const std::vector<TfLiteTensor*>& input_tensors, ++ const std::string& input) { + return preprocessor_->Preprocess(input); + } + +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.h +index fb85a977c971a..b76b74ea78bce 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.h ++++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.h +@@ -77,7 +77,8 @@ class TextEmbedder + // + // [1]: https://en.wikipedia.org/wiki/Cosine_similarity + static tflite::support::StatusOr<double> CosineSimilarity( +- const processor::FeatureVector& u, const processor::FeatureVector& v); ++ const processor::FeatureVector& u, ++ const processor::FeatureVector& v); + + protected: + // The options used to build this TextEmbedder. diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.cc -index 069491f6e47c9..2937a175c5e3c 100644 +index c093e9a621e5c..18a73b0add7f9 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.cc -@@ -21,7 +21,7 @@ limitations under the License. +@@ -22,7 +22,7 @@ limitations under the License. #include <vector> #include "absl/container/flat_hash_map.h" // from @com_google_absl @@ -2085,7 +2430,7 @@ #include "tensorflow_lite_support/cc/port/statusor.h" #include "tensorflow_lite_support/cc/task/core/base_task_api.h" #include "tensorflow_lite_support/cc/task/core/task_api_factory.h" -@@ -197,7 +197,8 @@ StatusOr<FeatureVector> UniversalSentenceEncoderQA::EncodeQuery( +@@ -183,7 +183,8 @@ StatusOr<FeatureVector> UniversalSentenceEncoderQA::EncodeQuery( } StatusOr<FeatureVector> UniversalSentenceEncoderQA::EncodeResponse( @@ -2095,7 +2440,7 @@ if (response_text.empty() && response_context.empty()) { return Status( StatusCode::kInvalidArgument, -@@ -218,7 +219,8 @@ StatusOr<float> UniversalSentenceEncoderQA::Similarity(const FeatureVector& a, +@@ -204,7 +205,8 @@ StatusOr<float> UniversalSentenceEncoderQA::Similarity(const FeatureVector& a, } std::vector<size_t> UniversalSentenceEncoderQA::Top( @@ -2105,17 +2450,17 @@ // Ensure k in [0, total_size). // If k == 0, it means that all outputs are ranked. if (k == 0) { -@@ -242,7 +244,8 @@ std::vector<size_t> UniversalSentenceEncoderQA::Top( +@@ -228,7 +230,8 @@ std::vector<size_t> UniversalSentenceEncoderQA::Top( } Status UniversalSentenceEncoderQA::Preprocess( - const std::vector<TfLiteTensor*>& input_tensors, const QAInput& input) { + const std::vector<TfLiteTensor*>& input_tensors, + const QAInput& input) { - auto* input_tensor_metadatas = - GetMetadataExtractor()->GetInputTensorMetadata(); - TfLiteTensor* query_text_tensor = -@@ -293,7 +296,8 @@ StatusOr<QAOutput> UniversalSentenceEncoderQA::Postprocess( + RETURN_IF_ERROR( + PopulateTensor(input.query_text, input_tensors[input_indices_[0]])); + RETURN_IF_ERROR( +@@ -249,7 +252,8 @@ StatusOr<QAOutput> UniversalSentenceEncoderQA::Postprocess( } internal::QAOutput UniversalSentenceEncoderQA::Run( @@ -2124,12 +2469,12 @@ + absl::string_view response_text, absl::string_view response_context) { QAInput input; - input.query_text = query_text; + input.query_text = std::string(query_text); diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h -index fae2f29721722..0269033918cc9 100644 +index 450f3001cdae8..8a05998a1baeb 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h -@@ -20,14 +20,14 @@ limitations under the License. +@@ -20,8 +20,8 @@ limitations under the License. #include <vector> #include "absl/container/flat_hash_map.h" // from @com_google_absl @@ -2140,14 +2485,7 @@ #include "tensorflow_lite_support/cc/port/statusor.h" #include "tensorflow_lite_support/cc/task/core/base_task_api.h" #include "tensorflow_lite_support/cc/task/core/task_api_factory.h" - #include "tensorflow_lite_support/cc/task/core/tflite_engine.h" --#include "tensorflow_lite_support/cc/task/text/proto/retrieval.pb.h" - #include "tensorflow_lite_support/cc/task/processor/proto/embedding.pb.h" -+#include "tensorflow_lite_support/cc/task/text/proto/retrieval.pb.h" - - namespace tflite { - namespace task { -@@ -73,7 +73,8 @@ class UniversalSentenceEncoderQA +@@ -88,7 +88,8 @@ class UniversalSentenceEncoderQA // Encodes response from the text and/or context. // Returns an error, if both text and context are empty. tflite::support::StatusOr<FeatureVector> EncodeResponse( @@ -2515,10 +2853,10 @@ // Performs pre-initialization actions. virtual absl::Status PreInit(); diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/image_segmenter.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/image_segmenter.cc -index f87c6b078eddc..20a34a956200b 100644 +index c9dad866f1a68..1cf9a54b91e0f 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/image_segmenter.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/image_segmenter.cc -@@ -17,8 +17,8 @@ limitations under the License. +@@ -17,10 +17,10 @@ limitations under the License. #include <algorithm> @@ -2527,8 +2865,11 @@ +#include "absl/memory/memory.h" // from @com_google_absl +#include "absl/strings/str_format.h" // from @com_google_absl #include "absl/strings/string_view.h" // from @com_google_absl - #include "flatbuffers/flatbuffers.h" // from @flatbuffers +-#include "flatbuffers/flatbuffers.h" // from @flatbuffers ++#include "flatbuffers/flatbuffers.h" // from @flatbuffers #include "tensorflow/lite/c/common.h" + #include "tensorflow_lite_support/cc/common.h" + #include "tensorflow_lite_support/cc/port/integral_types.h" @@ -110,7 +110,8 @@ constexpr uint8 kColorMap[768] = { StatusOr<std::vector<LabelMapItem>> GetLabelMapIfAny( @@ -2588,7 +2929,7 @@ // Prebuilt list of ColoredLabel attached to each Segmentation result. The // i-th item in this list corresponds to the i-th label map item. diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/object_detector.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/object_detector.cc -index 872bd8d5876a4..3eb512699bbda 100644 +index 0a4d5f7553ee9..ade2de74cf728 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/object_detector.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/object_detector.cc @@ -20,9 +20,9 @@ limitations under the License. @@ -2658,30 +2999,6 @@ // Performs sanity checks on the provided ObjectDetectorOptions. static absl::Status SanityCheckOptions(const ObjectDetectorOptions& options); -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/segmentations.proto b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/segmentations.proto -index 259bee8194735..f6df558cc1a1a 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/segmentations.proto -+++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/segmentations.proto -@@ -31,17 +31,13 @@ message Segmentation { - // pixel, the value indicates the prediction confidence usually in the [0, 1] - // range where higher values represent a stronger confidence. Ultimately this - // is model specific, and other range of values might be used. -- message ConfidenceMask { -- repeated float value = 1 [packed = true]; -- } -+ message ConfidenceMask { repeated float value = 1 [packed = true]; } - - // List of confidence masks with respect to the model output depth (this depth - // represents how many classes are supported). Note: some models have a single - // class (e.g. a sky segmentation model) which turns into a single confidence - // mask in this list. -- message ConfidenceMasks { -- repeated ConfidenceMask confidence_mask = 1; -- } -+ message ConfidenceMasks { repeated ConfidenceMask confidence_mask = 1; } - - // IMPORTANT: segmentation masks are not direcly suited for display, in - // particular: diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/utils/frame_buffer_common_utils.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/utils/frame_buffer_common_utils.cc index f30af1e7d27d8..cea7ef3fb1f23 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/utils/frame_buffer_common_utils.cc @@ -3831,8 +4148,70 @@ std::vector<core::Category> results = classifier->Classify(kInputStr); std::vector<core::Category> expected_class = { {"label0", 255}, +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/text/text_embedder_test.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/text/text_embedder_test.cc +index 812d91ff65d93..6bf72b83c9204 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/text/text_embedder_test.cc ++++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/text/text_embedder_test.cc +@@ -17,7 +17,7 @@ limitations under the License. + + #include <iostream> + +-#include "absl/status/status.h" // from @com_google_absl ++#include "absl/status/status.h" // from @com_google_absl + #include "absl/strings/string_view.h" // from @com_google_absl + #include "tensorflow/lite/core/shims/cc/shims_test_util.h" + #include "tensorflow_lite_support/cc/port/gmock.h" +@@ -52,8 +52,8 @@ class CreateFromOptionsTest : public tflite_shims::testing::Test {}; + + TextEmbedderOptions GetBasicOptions(absl::string_view model_name) { + TextEmbedderOptions options; +- options.mutable_base_options()->mutable_model_file()->set_file_name(JoinPath( +- "./" /*test src dir*/, kTestDataDirectory, model_name)); ++ options.mutable_base_options()->mutable_model_file()->set_file_name( ++ JoinPath("./" /*test src dir*/, kTestDataDirectory, model_name)); + return options; + } + +@@ -126,7 +126,7 @@ TEST(EmbedTest, SucceedsWithRegexModel) { + TextEmbedderOptions options = GetBasicOptions(kRegexOneEmbeddingModel); + // No Embedding options means all head get a default option. + SUPPORT_ASSERT_OK_AND_ASSIGN(std::unique_ptr<TextEmbedder> text_embedder, +- TextEmbedder::CreateFromOptions(options)); ++ TextEmbedder::CreateFromOptions(options)); + + SUPPORT_ASSERT_OK_AND_ASSIGN( + auto result0, +@@ -137,8 +137,8 @@ TEST(EmbedTest, SucceedsWithRegexModel) { + EXPECT_NEAR(result0.embeddings(0).feature_vector().value_float(0), 0.0309356f, + kValueDiffTolerance); + +- SUPPORT_ASSERT_OK_AND_ASSIGN(auto result1, +- text_embedder->Embed("what a great and fantastic trip")); ++ SUPPORT_ASSERT_OK_AND_ASSIGN( ++ auto result1, text_embedder->Embed("what a great and fantastic trip")); + EXPECT_EQ(result1.embeddings_size(), 1); + EXPECT_EQ(result1.embeddings(0).feature_vector().value_float_size(), 16); + +@@ -158,7 +158,7 @@ TEST(GetEmbeddingDimension, Succeeds) { + // Create embedder. + TextEmbedderOptions options = GetBasicOptions(kMobileBert); + SUPPORT_ASSERT_OK_AND_ASSIGN(std::unique_ptr<TextEmbedder> text_embedder, +- TextEmbedder::CreateFromOptions(options)); ++ TextEmbedder::CreateFromOptions(options)); + + EXPECT_EQ(text_embedder->GetEmbeddingDimension(0), 512); + EXPECT_EQ(text_embedder->GetEmbeddingDimension(1), -1); +@@ -169,7 +169,7 @@ TEST(GetNumberOfOutputLayers, Succeeds) { + TextEmbedderOptions options = GetBasicOptions(kMobileBert); + // No Embedding options means all head get a default option. + SUPPORT_ASSERT_OK_AND_ASSIGN(std::unique_ptr<TextEmbedder> text_embedder, +- TextEmbedder::CreateFromOptions(options)); ++ TextEmbedder::CreateFromOptions(options)); + EXPECT_EQ(text_embedder->GetNumberOfOutputLayers(), kNumberOfOutputLayers); + } + diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/image_classifier_test.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/image_classifier_test.cc -index 6da6b6f7a2da3..ae4e48cac2410 100644 +index 86711635ce467..c40836ed3b125 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/image_classifier_test.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/image_classifier_test.cc @@ -17,9 +17,9 @@ limitations under the License. @@ -3969,7 +4348,30 @@ StatusOr<ClassificationResult> result_or = image_classifier->Classify(*frame_buffer); -@@ -426,11 +425,11 @@ TEST(ClassifyTest, SucceedsWithBaseOptions) { +@@ -452,8 +451,8 @@ TEST(ClassifyTest, SucceedsWithMiniBenchmark) { + rgb_image.pixel_data, + FrameBuffer::Dimension{rgb_image.width, rgb_image.height}); + +- auto file_name = JoinPath("./" /*test src dir*/, +- kTestDataDirectory, kMobileNetFloatWithMetadata); ++ auto file_name = JoinPath("./" /*test src dir*/, kTestDataDirectory, ++ kMobileNetFloatWithMetadata); + + ImageClassifierOptions options; + options.set_max_results(3); +@@ -462,8 +461,9 @@ TEST(ClassifyTest, SucceedsWithMiniBenchmark) { + + ConfigureXnnPackMiniBenchmark(/*num_threads=*/2, options); + +- SUPPORT_ASSERT_OK_AND_ASSIGN(std::unique_ptr<ImageClassifier> image_classifier, +- ImageClassifier::CreateFromOptions(options)); ++ SUPPORT_ASSERT_OK_AND_ASSIGN( ++ std::unique_ptr<ImageClassifier> image_classifier, ++ ImageClassifier::CreateFromOptions(options)); + + StatusOr<ClassificationResult> result_or = + image_classifier->Classify(*frame_buffer); +@@ -493,11 +493,11 @@ TEST(ClassifyTest, SucceedsWithMiniBenchmark) { TEST(ClassifyTest, GetInputCountSucceeds) { ImageClassifierOptions options; @@ -3986,7 +4388,7 @@ int32_t input_count = image_classifier->GetInputCount(); EXPECT_THAT(input_count, 1); -@@ -438,11 +437,11 @@ TEST(ClassifyTest, GetInputCountSucceeds) { +@@ -505,11 +505,11 @@ TEST(ClassifyTest, GetInputCountSucceeds) { TEST(ClassifyTest, GetInputShapeSucceeds) { ImageClassifierOptions options; @@ -4003,7 +4405,7 @@ // Verify the shape array size. const TfLiteIntArray* input_shape_0 = image_classifier->GetInputShape(0); -@@ -456,11 +455,11 @@ TEST(ClassifyTest, GetInputShapeSucceeds) { +@@ -523,11 +523,11 @@ TEST(ClassifyTest, GetInputShapeSucceeds) { TEST(ClassifyTest, GetOutputCountSucceeds) { ImageClassifierOptions options; @@ -4020,7 +4422,7 @@ int32_t output_count = image_classifier->GetOutputCount(); EXPECT_THAT(output_count, 1); -@@ -468,11 +467,11 @@ TEST(ClassifyTest, GetOutputCountSucceeds) { +@@ -535,11 +535,11 @@ TEST(ClassifyTest, GetOutputCountSucceeds) { TEST(ClassifyTest, GetOutputShapeSucceeds) { ImageClassifierOptions options; @@ -4037,7 +4439,7 @@ // Verify the shape array size. const TfLiteIntArray* output_shape_0 = image_classifier->GetOutputShape(0); -@@ -537,9 +536,8 @@ class PostprocessTest : public tflite_shims::testing::Test { +@@ -604,9 +604,8 @@ class PostprocessTest : public tflite_shims::testing::Test { TEST_F(PostprocessTest, SucceedsWithMaxResultsOption) { ImageClassifierOptions options; @@ -4049,7 +4451,7 @@ options.set_max_results(3); SetUp(options); -@@ -551,9 +549,10 @@ TEST_F(PostprocessTest, SucceedsWithMaxResultsOption) { +@@ -618,9 +617,10 @@ TEST_F(PostprocessTest, SucceedsWithMaxResultsOption) { std::vector<uint8_t> scores = {/*daisy*/ 0, /*dandelion*/ 64, /*roses*/ 255, /*sunflowers*/ 32, /*tulips*/ 128}; SUPPORT_ASSERT_OK(PopulateTensor(scores, output_tensor)); @@ -4063,7 +4465,7 @@ ExpectApproximatelyEqual( result, ParseTextProtoOrDie<ClassificationResult>( -@@ -568,9 +567,8 @@ TEST_F(PostprocessTest, SucceedsWithMaxResultsOption) { +@@ -635,9 +635,8 @@ TEST_F(PostprocessTest, SucceedsWithMaxResultsOption) { TEST_F(PostprocessTest, SucceedsWithScoreThresholdOption) { ImageClassifierOptions options; @@ -4075,7 +4477,7 @@ options.set_score_threshold(0.4); SetUp(options); -@@ -582,9 +580,10 @@ TEST_F(PostprocessTest, SucceedsWithScoreThresholdOption) { +@@ -649,9 +648,10 @@ TEST_F(PostprocessTest, SucceedsWithScoreThresholdOption) { std::vector<uint8_t> scores = {/*daisy*/ 0, /*dandelion*/ 64, /*roses*/ 255, /*sunflowers*/ 32, /*tulips*/ 128}; SUPPORT_ASSERT_OK(PopulateTensor(scores, output_tensor)); @@ -4089,7 +4491,7 @@ ExpectApproximatelyEqual( result, -@@ -599,9 +598,8 @@ TEST_F(PostprocessTest, SucceedsWithScoreThresholdOption) { +@@ -666,9 +666,8 @@ TEST_F(PostprocessTest, SucceedsWithScoreThresholdOption) { TEST_F(PostprocessTest, SucceedsWithWhitelistOption) { ImageClassifierOptions options; @@ -4101,7 +4503,7 @@ options.add_class_name_whitelist("dandelion"); options.add_class_name_whitelist("daisy"); -@@ -614,9 +612,10 @@ TEST_F(PostprocessTest, SucceedsWithWhitelistOption) { +@@ -681,9 +680,10 @@ TEST_F(PostprocessTest, SucceedsWithWhitelistOption) { std::vector<uint8_t> scores = {/*daisy*/ 0, /*dandelion*/ 64, /*roses*/ 255, /*sunflowers*/ 32, /*tulips*/ 128}; SUPPORT_ASSERT_OK(PopulateTensor(scores, output_tensor)); @@ -4115,7 +4517,7 @@ ExpectApproximatelyEqual( result, ParseTextProtoOrDie<ClassificationResult>( -@@ -630,9 +629,8 @@ TEST_F(PostprocessTest, SucceedsWithWhitelistOption) { +@@ -697,9 +697,8 @@ TEST_F(PostprocessTest, SucceedsWithWhitelistOption) { TEST_F(PostprocessTest, SucceedsWithBlacklistOption) { ImageClassifierOptions options; @@ -4127,7 +4529,7 @@ options.add_class_name_blacklist("dandelion"); options.add_class_name_blacklist("daisy"); -@@ -645,9 +643,10 @@ TEST_F(PostprocessTest, SucceedsWithBlacklistOption) { +@@ -712,9 +711,10 @@ TEST_F(PostprocessTest, SucceedsWithBlacklistOption) { std::vector<uint8_t> scores = {/*daisy*/ 0, /*dandelion*/ 64, /*roses*/ 255, /*sunflowers*/ 32, /*tulips*/ 128}; SUPPORT_ASSERT_OK(PopulateTensor(scores, output_tensor)); @@ -6470,27 +6872,25 @@ "device."); diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_demo.cc b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_demo.cc -index 8c4a36c31674f..8ba00cb5d50bd 100644 +index 1144fa2c100ab..a46c60ab075fd 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_demo.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_demo.cc -@@ -14,26 +14,30 @@ limitations under the License. +@@ -14,9 +14,9 @@ limitations under the License. ==============================================================================*/ // Demostration the usage of UniversalSentenceEncoderQA. --#include "tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h" +-#include "absl/flags/flag.h" // from @com_google_absl +-#include "absl/flags/parse.h" // from @com_google_absl +-#include "absl/status/status.h" // from @com_google_absl +#include "absl/flags/flag.h" // from @com_google_absl +#include "absl/flags/parse.h" // from @com_google_absl +#include "absl/status/status.h" // from @com_google_absl #include "absl/strings/str_split.h" // from @com_google_absl --#include "absl/flags/flag.h" // from @com_google_absl --#include "absl/flags/parse.h" // from @com_google_absl --#include "absl/status/status.h" // from @com_google_absl --using tflite::task::text::RetrievalOptions; -+#include "tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h" - using tflite::task::text::RetrievalInput; -+using tflite::task::text::RetrievalOptions; - using tflite::task::text::RetrievalOutput; - using tflite::task::text::retrieval::UniversalSentenceEncoderQA; + #include "tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h" + #include "tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_op_resolver.h" +@@ -29,12 +29,17 @@ using tflite::task::text::RetrievalOutput; + using tflite::task::text::UniversalSentenceEncoderQA; + } // namespace -ABSL_FLAG(std::string, model_path, "", +ABSL_FLAG(std::string, @@ -6509,33 +6909,6 @@ "I'm not feeling very well.:Paris is the capital of France.:He looks good.", "Candidate answers seperated by `:`."); -- - int main(int argc, char** argv) { - // Parse command line arguments and perform sanity checks. - absl::ParseCommandLine(argc, argv); -@@ -55,8 +59,8 @@ int main(int argc, char** argv) { - absl::GetFlag(FLAGS_model_path)); - auto status = UniversalSentenceEncoderQA::CreateFromOption(options); - CHECK_OK(status); -- std::unique_ptr<UniversalSentenceEncoderQA> client -- = std::move(status.value()); -+ std::unique_ptr<UniversalSentenceEncoderQA> client = -+ std::move(status.value()); - - // Create RetrievalInput with a query and responses. - RetrievalInput input; -@@ -80,8 +84,8 @@ int main(int argc, char** argv) { - // Consume the results according to the ranking. Here we just print them out. - std::cout << input.query_text() << std::endl; - for (size_t k : top) { -- std::cout << input.responses(k).raw_text().text() << ", " -- << input.responses(k).raw_text().context() << ", " -- << output.response_results(k).score() << std::endl; -+ std::cout << input.responses(k).raw_text().text() << ", " -+ << input.responses(k).raw_text().context() << ", " -+ << output.response_results(k).score() << std::endl; - } - } diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/image_classifier_demo.cc b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/image_classifier_demo.cc index 8b2ed939686b3..bd2aaaf188726 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/image_classifier_demo.cc @@ -6793,7 +7166,7 @@ "device."); diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.cc b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.cc -index 6f3aa737bd090..efdcda993f5e8 100644 +index e0a8a4c36ddc4..d5c0c589e375c 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.cc @@ -23,11 +23,11 @@ limitations under the License. @@ -6811,8 +7184,8 @@ +#include "stb_image_write.h" // from @stblib #include "tensorflow_lite_support/cc/port/status_macros.h" #include "tensorflow_lite_support/cc/port/statusor.h" - -@@ -87,7 +87,9 @@ absl::Status EncodeImageToPngFile(const ImageData& image_data, + #include "tensorflow_lite_support/cc/task/vision/utils/frame_buffer_common_utils.h" +@@ -88,7 +88,9 @@ absl::Status EncodeImageToPngFile(const ImageData& image_data, return absl::OkStatus(); } @@ -6821,10 +7194,10 @@ + stbi_image_free(image->pixel_data); +} - } // namespace vision - } // namespace task + tflite::support::StatusOr<std::unique_ptr<FrameBuffer>> + CreateFrameBufferFromImageData(const ImageData& image) { diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.h b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.h -index a0b0c6bbad191..9e7e3ba500f2d 100644 +index 6ba5c2d6490ab..7de32ee9c0f53 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.h @@ -15,7 +15,7 @@ limitations under the License. @@ -6868,10 +7241,10 @@ TFLSupportErrorCodeInternalError, } NS_SWIFT_NAME(SupportErrorCode); diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.h -index 8ef21659a4a1a..a194b2834323a 100644 +index 2a374ccf19421..686a996e04b75 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.h -@@ -21,42 +21,43 @@ NS_ASSUME_NONNULL_BEGIN +@@ -21,39 +21,39 @@ NS_ASSUME_NONNULL_BEGIN @interface TFLCommonUtils : NSObject /** @@ -6882,16 +7255,12 @@ * * @param code Error code. * @param description Error description. -- * @param error Pointer to the memory location where the created error should be saved. If `nil`, no -- * error will be saved. -+ * @param error Pointer to the memory location where the created error should be -+ * saved. If `nil`, no error will be saved. + * @return A NSError instance. */ - + (void)customErrorWithCode:(NSInteger)code -- description:(NSString *)description -- error:(NSError **)error; -+ description:(NSString*)description -+ error:(NSError**)error; +-+ (NSError *)customErrorWithCode:(NSInteger)code +- description:(NSString *)description; +++ (NSError*)customErrorWithCode:(NSInteger)code ++ description:(NSString*)description; /** - * Creates and saves an error originating from the task library from a C library error, @@ -6900,14 +7269,10 @@ + * error, TfLiteSupportError . * * @param supportError C library error. -- * @param error Pointer to the memory location where the created error should be saved. If `nil`, no -- * error will be saved. -+ * @param error Pointer to the memory location where the created error should be -+ * saved. If `nil`, no error will be saved. + * @return A NSError instance. */ --+ (void)errorFromTfLiteSupportError:(TfLiteSupportError *)supportError error:(NSError **)error; -++ (void)errorFromTfLiteSupportError:(TfLiteSupportError*)supportError -+ error:(NSError**)error; +-+ (NSError *)errorWithCError:(TfLiteSupportError *)supportError; +++ (NSError*)errorWithCError:(TfLiteSupportError*)supportError; /** - * Allocates a block of memory with the specified size and returns a pointer to it. If memory cannot @@ -6935,99 +7300,19 @@ @end NS_ASSUME_NONNULL_END -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.m -index 6fc2eadeeafe9..2f2d85a23593a 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.m -@@ -16,39 +16,43 @@ - #import "tensorflow_lite_support/ios/sources/TFLCommon.h" - - /** Error domain of TensorFlow Lite Support related errors. */ --static NSString *const TFLSupportTaskErrorDomain = @"org.tensorflow.lite.tasks"; -+static NSString* const TFLSupportTaskErrorDomain = @"org.tensorflow.lite.tasks"; - - @implementation TFLCommonUtils - - + (void)customErrorWithCode:(NSInteger)code -- description:(NSString *)description -- error:(NSError **)error { -+ description:(NSString*)description -+ error:(NSError**)error { - if (error) -- *error = [NSError errorWithDomain:TFLSupportTaskErrorDomain -- code:code -- userInfo:@{NSLocalizedDescriptionKey : description}]; -+ *error = -+ [NSError errorWithDomain:TFLSupportTaskErrorDomain -+ code:code -+ userInfo:@{NSLocalizedDescriptionKey : description}]; - } - --+ (void)errorFromTfLiteSupportError:(TfLiteSupportError *)supportError error:(NSError **)error { -++ (void)errorFromTfLiteSupportError:(TfLiteSupportError*)supportError -+ error:(NSError**)error { - if (supportError && error) -- *error = [NSError -- errorWithDomain:TFLSupportTaskErrorDomain -- code:supportError->code -- userInfo:@{ -- NSLocalizedDescriptionKey : [NSString stringWithCString:supportError->message -- encoding:NSUTF8StringEncoding] -- }]; -+ *error = [NSError errorWithDomain:TFLSupportTaskErrorDomain -+ code:supportError->code -+ userInfo:@{ -+ NSLocalizedDescriptionKey : [NSString -+ stringWithCString:supportError->message -+ encoding:NSUTF8StringEncoding] -+ }]; - } - --+ (void *)mallocWithSize:(size_t)memSize error:(NSError **)error { -++ (void*)mallocWithSize:(size_t)memSize error:(NSError**)error { - if (!memSize) { -- [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError -- description:@"Invalid memory size passed for allocation of object." -- error:error]; -+ [TFLCommonUtils -+ customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError -+ description: -+ @"Invalid memory size passed for allocation of object." -+ error:error]; - return NULL; - } - -- void *allocedMemory = malloc(memSize); -+ void* allocedMemory = malloc(memSize); - if (!allocedMemory && memSize) { - exit(-1); - } diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.h -index 40ba41b8eb0f9..90864c703c411 100644 +index a117bd7b3c4c3..5058f7c9a5a7b 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.h @@ -18,7 +18,7 @@ NS_ASSUME_NONNULL_BEGIN @interface TFLBaseOptions (Helpers) --- (void)copyBaseOptionsToCBaseOptions:(TfLiteBaseOptions *)cBaseOptions; -+- (void)copyBaseOptionsToCBaseOptions:(TfLiteBaseOptions*)cBaseOptions; +-- (void)copyToCOptions:(TfLiteBaseOptions *)cBaseOptions; ++- (void)copyToCOptions:(TfLiteBaseOptions*)cBaseOptions; @end NS_ASSUME_NONNULL_END -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.m -index 0fed6d7c9966e..ddab0f7ab4207 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.m -@@ -16,7 +16,7 @@ - - @implementation TFLBaseOptions (Helpers) - --- (void)copyBaseOptionsToCBaseOptions:(TfLiteBaseOptions *)cBaseOptions { -+- (void)copyBaseOptionsToCBaseOptions:(TfLiteBaseOptions*)cBaseOptions { - if (self.modelFile.filePath) { - cBaseOptions->model_file.file_path = self.modelFile.filePath.UTF8String; - } diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.h index cdcddabe7323a..0f92dd1005631 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.h @@ -7099,66 +7384,56 @@ @end -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.m -index 826380f1f62db..1e536cdc08194 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.m -@@ -25,8 +25,8 @@ - return self; - } +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.h +index 617fa3ae7120e..6f515e46744b9 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.h ++++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.h +@@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN + * results returned by inference methods of the iOS TF Lite Task Classification + * tasks. + */ +-+ (TFLCategory *)categoryWithCCategory:(TfLiteCategory *)cCategory; +++ (TFLCategory*)categoryWithCCategory:(TfLiteCategory*)cCategory; + @end --- (id)copyWithZone:(NSZone *)zone { -- TFLCpuSettings *cpuSettings = [[TFLCpuSettings alloc] init]; -+- (id)copyWithZone:(NSZone*)zone { -+ TFLCpuSettings* cpuSettings = [[TFLCpuSettings alloc] init]; + NS_ASSUME_NONNULL_END +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h +index 655e892ffec73..9188fc008d0b8 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h ++++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h +@@ -20,16 +20,16 @@ NS_ASSUME_NONNULL_BEGIN + @interface TFLCategory : NSObject - [cpuSettings setNumThreads:self.numThreads]; + /** Display name of the class. */ +-@property(nonatomic, copy) NSString *displayName; ++@property(nonatomic, copy) NSString* displayName; -@@ -46,8 +46,8 @@ - return self; - } + /** Class name of the class . */ +-@property(nonatomic, copy) NSString *label; ++@property(nonatomic, copy) NSString* label; --- (id)copyWithZone:(NSZone *)zone { -- TFLComputeSettings *computeSettings = [[TFLComputeSettings alloc] init]; -+- (id)copyWithZone:(NSZone*)zone { -+ TFLComputeSettings* computeSettings = [[TFLComputeSettings alloc] init]; + /** Confidence score for this class . */ + @property(nonatomic, assign) float score; - [computeSettings setCpuSettings:self.cpuSettings]; +-/** The index of the class in the corresponding label map, usually packed in the TFLite Model +- * Metadata. */ ++/** The index of the class in the corresponding label map, usually packed in the ++ * TFLite Model Metadata. */ + @property(nonatomic, assign) NSInteger classIndex; -@@ -59,8 +59,8 @@ - @implementation TFLExternalFile - @synthesize filePath; - --- (id)copyWithZone:(NSZone *)zone { -- TFLExternalFile *externalFile = [[TFLExternalFile alloc] init]; -+- (id)copyWithZone:(NSZone*)zone { -+ TFLExternalFile* externalFile = [[TFLExternalFile alloc] init]; - - [externalFile setFilePath:self.filePath]; - -@@ -82,8 +82,8 @@ - return self; - } - --- (id)copyWithZone:(NSZone *)zone { -- TFLBaseOptions *baseOptions = [[TFLBaseOptions alloc] init]; -+- (id)copyWithZone:(NSZone*)zone { -+ TFLBaseOptions* baseOptions = [[TFLBaseOptions alloc] init]; - - [baseOptions setModelFile:self.modelFile]; - [baseOptions setComputeSettings:self.computeSettings]; + @end diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.h -index 623065d416904..78a1f965769aa 100644 +index 4381c489c26ad..33ecd084382fc 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.h -@@ -19,11 +19,11 @@ NS_ASSUME_NONNULL_BEGIN +@@ -18,11 +18,11 @@ + NS_ASSUME_NONNULL_BEGIN @interface TFLClassificationOptions (Helpers) - - (BOOL)copyClassificationOptionsToCClassificationOptions: -- (TfLiteClassificationOptions *)cClassificationOptions -- error:(NSError **)error; -+ (TfLiteClassificationOptions*)cClassificationOptions -+ error:(NSError**)error; +-- (BOOL)copyToCOptions:(TfLiteClassificationOptions *)cClassificationOptions +- error:(NSError **)error; ++- (BOOL)copyToCOptions:(TfLiteClassificationOptions*)cClassificationOptions ++ error:(NSError**)error; - (void)deleteCStringArraysOfClassificationOptions: - (TfLiteClassificationOptions *)cClassificationOptions; @@ -7166,137 +7441,6 @@ @end NS_ASSUME_NONNULL_END -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.m -index f7aa5fdf18b36..07254ab675c4b 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.m -@@ -18,28 +18,35 @@ - - @implementation TFLClassificationOptions (Helpers) - --+ (char **)cStringArrayFromNSArray:(NSArray<NSString *> *)strings error:(NSError **)error { -++ (char**)cStringArrayFromNSArray:(NSArray<NSString*>*)strings -+ error:(NSError**)error { - if (strings.count <= 0) { -- [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError -- description:@"Invalid length of strings found for list type options." -- error:error]; -+ [TFLCommonUtils -+ customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError -+ description: -+ @"Invalid length of strings found for list type options." -+ error:error]; - return NULL; - } - -- char **cStrings = (char **)calloc(strings.count, sizeof(char *)); -+ char** cStrings = (char**)calloc(strings.count, sizeof(char*)); - - if (!cStrings) { -- [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeInternalError -- description:@"Could not initialize list type options." -- error:error]; -+ [TFLCommonUtils -+ customErrorWithCode:TFLSupportErrorCodeInternalError -+ description:@"Could not initialize list type options." -+ error:error]; - return nil; - } - - for (NSInteger i = 0; i < strings.count; i++) { -- char *cString = [TFLCommonUtils -- mallocWithSize:[strings[i] lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1 -+ char* cString = [TFLCommonUtils -+ mallocWithSize:[strings[i] -+ lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + -+ 1 - error:error]; -- if (!cString) return nil; -+ if (!cString) -+ return nil; - - strcpy(cString, strings[i].UTF8String); - } -@@ -47,7 +54,7 @@ - return cStrings; - } - --+ (void)deleteCStringsArray:(char **)cStrings count:(int)count { -++ (void)deleteCStringsArray:(char**)cStrings count:(int)count { - for (NSInteger i = 0; i < count; i++) { - free(cStrings[i]); - } -@@ -56,49 +63,56 @@ - } - - - (BOOL)copyClassificationOptionsToCClassificationOptions: -- (TfLiteClassificationOptions *)cClassificationOptions -- error:(NSError **)error { -+ (TfLiteClassificationOptions*)cClassificationOptions -+ error:(NSError**)error { - cClassificationOptions->score_threshold = self.scoreThreshold; - cClassificationOptions->max_results = (int)self.maxResults; - - if (self.labelDenyList) { -- char **cClassNameBlackList = -- [TFLClassificationOptions cStringArrayFromNSArray:self.labelDenyList error:error]; -+ char** cClassNameBlackList = -+ [TFLClassificationOptions cStringArrayFromNSArray:self.labelDenyList -+ error:error]; - if (!cClassNameBlackList) { - return NO; - } - cClassificationOptions->label_denylist.list = cClassNameBlackList; -- cClassificationOptions->label_denylist.length = (int)self.labelDenyList.count; -+ cClassificationOptions->label_denylist.length = -+ (int)self.labelDenyList.count; - } - - if (self.labelAllowList) { -- char **cClassNameWhiteList = -- [TFLClassificationOptions cStringArrayFromNSArray:self.labelAllowList error:error]; -+ char** cClassNameWhiteList = -+ [TFLClassificationOptions cStringArrayFromNSArray:self.labelAllowList -+ error:error]; - if (!cClassNameWhiteList) { - return NO; - } - - cClassificationOptions->label_allowlist.list = cClassNameWhiteList; -- cClassificationOptions->label_allowlist.length = (int)self.labelAllowList.count; -+ cClassificationOptions->label_allowlist.length = -+ (int)self.labelAllowList.count; - } - - if (self.displayNamesLocal) { -- cClassificationOptions->display_names_local = (char *)self.displayNamesLocal.UTF8String; -+ cClassificationOptions->display_names_local = -+ (char*)self.displayNamesLocal.UTF8String; - } - - return YES; - } - - - (void)deleteCStringArraysOfClassificationOptions: -- (TfLiteClassificationOptions *)cClassificationOptions { -+ (TfLiteClassificationOptions*)cClassificationOptions { - if (self.labelAllowList) { -- [TFLClassificationOptions deleteCStringsArray:cClassificationOptions->label_allowlist.list -- count:cClassificationOptions->label_allowlist.length]; -+ [TFLClassificationOptions -+ deleteCStringsArray:cClassificationOptions->label_allowlist.list -+ count:cClassificationOptions->label_allowlist.length]; - } - - if (self.labelDenyList) { -- [TFLClassificationOptions deleteCStringsArray:cClassificationOptions->label_denylist.list -- count:cClassificationOptions->label_denylist.length]; -+ [TFLClassificationOptions -+ deleteCStringsArray:cClassificationOptions->label_denylist.list -+ count:cClassificationOptions->label_denylist.length]; - } - } - @end diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.h index dbe05c8f98d2f..cc0c8a87da148 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.h @@ -7320,47 +7464,44 @@ /** Results with score threshold greater than this value are returned . */ @property(nonatomic, assign) float scoreThreshold; -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.m -index 784f782ebc271..dca232d673238 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.m -@@ -30,8 +30,9 @@ - return self; - } +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.h +index 829d56def82ca..9c8b92c362806 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.h ++++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.h +@@ -20,17 +20,18 @@ NS_ASSUME_NONNULL_BEGIN + @interface TFLClassificationResult (Helpers) --- (id)copyWithZone:(NSZone *)zone { -- TFLClassificationOptions *classificationOptions = [[TFLClassificationOptions alloc] init]; -+- (id)copyWithZone:(NSZone*)zone { -+ TFLClassificationOptions* classificationOptions = -+ [[TFLClassificationOptions alloc] init]; + /** +- * Creates and retrurns a TFLClassificationResult from a TfLiteClassificationResult returned by +- * TFLite Task C Library Classification tasks. ++ * Creates and retrurns a TFLClassificationResult from a ++ * TfLiteClassificationResult returned by TFLite Task C Library Classification ++ * tasks. + * +- * @param cClassificationResult Classification results returned by TFLite Task C Library +- * Classification tasks ++ * @param cClassificationResult Classification results returned by TFLite Task C ++ * Library Classification tasks + * +- * @return Classification Result of type TFLClassificationResult to be returned by inference methods +- * of the iOS TF Lite Task Classification tasks. ++ * @return Classification Result of type TFLClassificationResult to be returned ++ * by inference methods of the iOS TF Lite Task Classification tasks. + */ +-+ (TFLClassificationResult *)classificationResultWithCResult: +- (TfLiteClassificationResult *)cClassificationResult; +++ (TFLClassificationResult*)classificationResultWithCResult: ++ (TfLiteClassificationResult*)cClassificationResult; + @end - [classificationOptions setScoreThreshold:self.scoreThreshold]; - [classificationOptions setMaxResults:self.maxResults]; + NS_ASSUME_NONNULL_END diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h -index 377e02f32045a..c0d6fb335ebf3 100644 +index ab4246e4caeee..500ec8faeafc5 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h -@@ -20,39 +20,40 @@ NS_ASSUME_NONNULL_BEGIN - @interface TFLCategory : NSObject +@@ -17,25 +17,26 @@ limitations under the License. - /** Display name of the class. */ --@property(nonatomic, copy) NSString *displayName; -+@property(nonatomic, copy) NSString* displayName; - - /** Class name of the class . */ --@property(nonatomic, copy) NSString *label; -+@property(nonatomic, copy) NSString* label; - - /** Confidence score for this class . */ - @property(nonatomic, assign) float score; - --/** The index of the class in the corresponding label map, usually packed in the TFLite Model -- * Metadata. */ -+/** The index of the class in the corresponding label map, usually packed in the -+ * TFLite Model Metadata. */ - @property(nonatomic, assign) NSInteger classIndex; - - @end + NS_ASSUME_NONNULL_BEGIN -/** Encapsulates list of predicted classes (aka labels) for a given image classifier head. */ +/** Encapsulates list of predicted classes (aka labels) for a given image @@ -7392,106 +7533,72 @@ @end -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.h -index 406eb1e4ceb5a..c52876e9a5d7a 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.h -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.h -@@ -19,22 +19,23 @@ +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.h +index ff2c546a884cc..81efbcc1d8c57 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.h ++++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.h +@@ -19,17 +19,17 @@ NS_ASSUME_NONNULL_BEGIN + + @interface TFLDetectionResult (Helpers) + /** +- * Creates and retrurns a TFLDetectionResult from a TfLiteDetectionResult returned by +- * TFLite Task C Library Object Detection task. ++ * Creates and retrurns a TFLDetectionResult from a TfLiteDetectionResult ++ * returned by TFLite Task C Library Object Detection task. + * + * @param cDetectionResult Detection results returned by TFLite Task C Library + * Object Detection task. + * +- * @return Detection Result of type TFLDetectionResult to be returned by inference methods +- * of the iOS TF Lite Task Object Detection task. ++ * @return Detection Result of type TFLDetectionResult to be returned by ++ * inference methods of the iOS TF Lite Task Object Detection task. + */ +-+ (TFLDetectionResult *)detectionResultWithCResult: +- (TfLiteDetectionResult *)cDetectionResult; +++ (TFLDetectionResult*)detectionResultWithCResult: ++ (TfLiteDetectionResult*)cDetectionResult; + @end + + NS_ASSUME_NONNULL_END +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.h +index d5b97506ec508..4d7fc0c0503fa 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.h ++++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.h +@@ -19,25 +19,26 @@ limitations under the License. NS_ASSUME_NONNULL_BEGIN --/** Helper utility for conversion between TFLite Task C Library Classification Results and iOS -- * Classification Results . */ -+/** Helper utility for conversion between TFLite Task C Library Classification -+ * Results and iOS Classification Results . */ - @interface TFLClassificationUtils : NSObject +-/** Encapsulates list of predicted classes (aka labels) and bounding box for a detected object. */ ++/** Encapsulates list of predicted classes (aka labels) and bounding box for a ++ * detected object. */ + @interface TFLDetection : NSObject /** -- * Creates and retrurns a TFLClassificationResult from a TfLiteClassificationResult returned by -- * TFLite Task C Library Classification tasks. -+ * Creates and retrurns a TFLClassificationResult from a -+ * TfLiteClassificationResult returned by TFLite Task C Library Classification -+ * tasks. - * -- * @param cClassificationResult Classification results returned by TFLite Task C Library -- * Classification tasks -+ * @param cClassificationResult Classification results returned by TFLite Task C -+ * Library Classification tasks - * -- * @return Classification Result of type TFLClassificationResult to be returned by inference methods -- * of the iOS TF Lite Task Classification tasks. -+ * @return Classification Result of type TFLClassificationResult to be returned -+ * by inference methods of the iOS TF Lite Task Classification tasks. +- * The index of the image classifier head these classes refer to. This is useful for multi-head +- * models. ++ * The index of the image classifier head these classes refer to. This is useful ++ * for multi-head models. */ --+ (TFLClassificationResult *)classificationResultFromCClassificationResults: -- (TfLiteClassificationResult *)cClassificationResult; -++ (TFLClassificationResult*)classificationResultFromCClassificationResults: -+ (TfLiteClassificationResult*)cClassificationResult; + @property(nonatomic, assign) CGRect boundingBox; - - (instancetype)init NS_UNAVAILABLE; +-/** The array of predicted classes, usually sorted by descending scores (e.g.from high to low +- * probability). */ +-@property(nonatomic, copy) NSArray<TFLCategory *> *categories; ++/** The array of predicted classes, usually sorted by descending scores ++ * (e.g.from high to low probability). */ ++@property(nonatomic, copy) NSArray<TFLCategory*>* categories; -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.m -index a24a91e5c9729..b5d884d39f864 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.m -@@ -16,39 +16,44 @@ + @end - @implementation TFLClassificationUtils + /** Encapsulates results of any object detection task. */ + @interface TFLDetectionResult : NSObject --+ (TFLClassificationResult *)classificationResultFromCClassificationResults: -- (TfLiteClassificationResult *)cClassificationResult { -- if (cClassificationResult == nil) return nil; -++ (TFLClassificationResult*)classificationResultFromCClassificationResults: -+ (TfLiteClassificationResult*)cClassificationResult { -+ if (cClassificationResult == nil) -+ return nil; +-@property(nonatomic, copy) NSArray<TFLDetection *> *detections; ++@property(nonatomic, copy) NSArray<TFLDetection*>* detections; -- NSMutableArray *classificationHeads = [[NSMutableArray alloc] init]; -+ NSMutableArray* classificationHeads = [[NSMutableArray alloc] init]; - for (int i = 0; i < cClassificationResult->size; i++) { -- TfLiteClassifications cClassifications = cClassificationResult->classifications[i]; -- NSMutableArray *classes = [[NSMutableArray alloc] init]; -+ TfLiteClassifications cClassifications = -+ cClassificationResult->classifications[i]; -+ NSMutableArray* classes = [[NSMutableArray alloc] init]; - for (int j = 0; j < cClassifications.size; j++) { - TfLiteCategory cCategory = cClassifications.categories[j]; -- TFLCategory *resultCategory = [[TFLCategory alloc] init]; -+ TFLCategory* resultCategory = [[TFLCategory alloc] init]; + @end - if (cCategory.display_name != nil) { -- resultCategory.displayName = [NSString stringWithCString:cCategory.display_name -- encoding:NSUTF8StringEncoding]; -+ resultCategory.displayName = -+ [NSString stringWithCString:cCategory.display_name -+ encoding:NSUTF8StringEncoding]; - } - - if (cCategory.label != nil) { -- resultCategory.label = [NSString stringWithCString:cCategory.label -- encoding:NSUTF8StringEncoding]; -+ resultCategory.label = -+ [NSString stringWithCString:cCategory.label -+ encoding:NSUTF8StringEncoding]; - } - - resultCategory.score = cCategory.score; - resultCategory.classIndex = (NSInteger)cCategory.index; - [classes addObject:resultCategory]; - } -- TFLClassifications *classificationHead = [[TFLClassifications alloc] init]; -+ TFLClassifications* classificationHead = [[TFLClassifications alloc] init]; - classificationHead.categories = classes; - classificationHead.headIndex = i; - [classificationHeads addObject:classificationHead]; - } - -- TFLClassificationResult *classificationResult = [[TFLClassificationResult alloc] init]; -+ TFLClassificationResult* classificationResult = -+ [[TFLClassificationResult alloc] init]; - classificationResult.classifications = classificationHeads; - return classificationResult; - } diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLBertNLClassifier.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLBertNLClassifier.h index 99de5ad04febf..ac81a15ac11c6 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLBertNLClassifier.h @@ -7549,70 +7656,6 @@ NS_SWIFT_NAME(classify(text:)); @end NS_ASSUME_NONNULL_END -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLBertNLClassifier.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLBertNLClassifier.m -index e9d3b3dbbd1e3..8c45ee62cceea 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLBertNLClassifier.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLBertNLClassifier.m -@@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN - - @interface TFLBertNLClassifier () - /** BertNLClassifier backed by C API */ --@property(nonatomic) TfLiteBertNLClassifier *bertNLClassifier; -+@property(nonatomic) TfLiteBertNLClassifier* bertNLClassifier; - @end - - @implementation TFLBertNLClassifier -@@ -34,24 +34,28 @@ NS_ASSUME_NONNULL_BEGIN - TfLiteBertNLClassifierDelete(_bertNLClassifier); - } - --+ (instancetype)bertNLClassifierWithModelPath:(NSString *)modelPath { -- TfLiteBertNLClassifier *classifier = TfLiteBertNLClassifierCreate(modelPath.UTF8String); -++ (instancetype)bertNLClassifierWithModelPath:(NSString*)modelPath { -+ TfLiteBertNLClassifier* classifier = -+ TfLiteBertNLClassifierCreate(modelPath.UTF8String); - - _GTMDevAssert(classifier, @"Failed to create BertNLClassifier"); - return [[TFLBertNLClassifier alloc] initWithBertNLClassifier:classifier]; - } - --+ (instancetype)bertNLClassifierWithModelPath:(NSString *)modelPath -- options:(TFLBertNLClassifierOptions *)options { -- // Note that maxSeqLen has been deprecated. Passing it to the C API is a no-op. -++ (instancetype)bertNLClassifierWithModelPath:(NSString*)modelPath -+ options: -+ (TFLBertNLClassifierOptions*)options { -+ // Note that maxSeqLen has been deprecated. Passing it to the C API is a -+ // no-op. - TfLiteBertNLClassifierOptions cOptions = {.max_seq_len = options.maxSeqLen}; -- TfLiteBertNLClassifier *classifier = -+ TfLiteBertNLClassifier* classifier = - TfLiteBertNLClassifierCreateFromOptions(modelPath.UTF8String, &cOptions); - _GTMDevAssert(classifier, @"Failed to create BertNLClassifier"); - return [[TFLBertNLClassifier alloc] initWithBertNLClassifier:classifier]; - } - --- (instancetype)initWithBertNLClassifier:(TfLiteBertNLClassifier *)bertNLClassifier { -+- (instancetype)initWithBertNLClassifier: -+ (TfLiteBertNLClassifier*)bertNLClassifier { - self = [super init]; - if (self) { - _bertNLClassifier = bertNLClassifier; -@@ -59,9 +63,11 @@ NS_ASSUME_NONNULL_BEGIN - return self; - } - --- (NSDictionary<NSString *, NSNumber *> *)classifyWithText:(NSString *)text { -- Categories *cCategories = TfLiteBertNLClassifierClassify(_bertNLClassifier, text.UTF8String); -- NSMutableDictionary<NSString *, NSNumber *> *ret = [NSMutableDictionary dictionary]; -+- (NSDictionary<NSString*, NSNumber*>*)classifyWithText:(NSString*)text { -+ Categories* cCategories = -+ TfLiteBertNLClassifierClassify(_bertNLClassifier, text.UTF8String); -+ NSMutableDictionary<NSString*, NSNumber*>* ret = -+ [NSMutableDictionary dictionary]; - for (int i = 0; i < cCategories->size; i++) { - Category cCategory = cCategories->categories[i]; - [ret setValue:[NSNumber numberWithDouble:cCategory.score] diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLNLClassifier.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLNLClassifier.h index ceb8d2ef9a307..41eb0fb76c9ea 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLNLClassifier.h @@ -7700,213 +7743,6 @@ NS_SWIFT_NAME(classify(text:)); @end NS_ASSUME_NONNULL_END -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLNLClassifier.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLNLClassifier.m -index 8d21a111345d2..39eb15c71681c 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLNLClassifier.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLNLClassifier.m -@@ -30,7 +30,7 @@ NS_ASSUME_NONNULL_BEGIN - - @interface TFLNLClassifier () - /** NLClassifier backed by C API */ --@property(nonatomic) TfLiteNLClassifier *nlClassifier; -+@property(nonatomic) TfLiteNLClassifier* nlClassifier; - @end - - @implementation TFLNLClassifier -@@ -39,8 +39,8 @@ NS_ASSUME_NONNULL_BEGIN - TfLiteNLClassifierDelete(_nlClassifier); - } - --+ (instancetype)nlClassifierWithModelPath:(NSString *)modelPath -- options:(TFLNLClassifierOptions *)options { -++ (instancetype)nlClassifierWithModelPath:(NSString*)modelPath -+ options:(TFLNLClassifierOptions*)options { - TfLiteNLClassifierOptions cOptions = { - .input_tensor_index = options.inputTensorIndex, - .output_score_tensor_index = options.outputScoreTensorIndex, -@@ -48,13 +48,13 @@ NS_ASSUME_NONNULL_BEGIN - .input_tensor_name = options.inputTensorName.UTF8String, - .output_score_tensor_name = options.outputScoreTensorName.UTF8String, - .output_label_tensor_name = options.outputLabelTensorName.UTF8String}; -- TfLiteNLClassifier *classifier = -+ TfLiteNLClassifier* classifier = - TfLiteNLClassifierCreateFromOptions(modelPath.UTF8String, &cOptions); - _GTMDevAssert(classifier, @"Failed to create NLClassifier"); - return [[TFLNLClassifier alloc] initWithNLClassifier:classifier]; - } - --- (instancetype)initWithNLClassifier:(TfLiteNLClassifier *)nlClassifier { -+- (instancetype)initWithNLClassifier:(TfLiteNLClassifier*)nlClassifier { - self = [super init]; - if (self) { - _nlClassifier = nlClassifier; -@@ -62,9 +62,11 @@ NS_ASSUME_NONNULL_BEGIN - return self; - } - --- (NSDictionary<NSString *, NSNumber *> *)classifyWithText:(NSString *)text { -- Categories *cCategories = TfLiteNLClassifierClassify(_nlClassifier, text.UTF8String); -- NSMutableDictionary<NSString *, NSNumber *> *ret = [NSMutableDictionary dictionary]; -+- (NSDictionary<NSString*, NSNumber*>*)classifyWithText:(NSString*)text { -+ Categories* cCategories = -+ TfLiteNLClassifierClassify(_nlClassifier, text.UTF8String); -+ NSMutableDictionary<NSString*, NSNumber*>* ret = -+ [NSMutableDictionary dictionary]; - for (int i = 0; i < cCategories->size; i++) { - Category cCategory = cCategories->categories[i]; - [ret setValue:[NSNumber numberWithDouble:cCategory.score] -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLBertNLClassifierTest.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLBertNLClassifierTest.m -index 9734fe7987a5e..407be10c1381c 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLBertNLClassifierTest.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLBertNLClassifierTest.m -@@ -19,8 +19,8 @@ limitations under the License. - NS_ASSUME_NONNULL_BEGIN - - @interface TFLBertNLClassifierTest : XCTestCase --@property(nonatomic, nullable) NSString *bertModelPath; --@property(nonatomic, nullable) TFLBertNLClassifierOptions *modelOptions; -+@property(nonatomic, nullable) NSString* bertModelPath; -+@property(nonatomic, nullable) TFLBertNLClassifierOptions* modelOptions; - @end - - @implementation TFLBertNLClassifierTest -@@ -28,30 +28,31 @@ NS_ASSUME_NONNULL_BEGIN - - - (void)setUp { - [super setUp]; -- NSBundle *bundle = [NSBundle bundleForClass:[self class]]; -- self.bertModelPath = [bundle pathForResource:@"bert_nl_classifier" ofType:@"tflite"]; -+ NSBundle* bundle = [NSBundle bundleForClass:[self class]]; -+ self.bertModelPath = [bundle pathForResource:@"bert_nl_classifier" -+ ofType:@"tflite"]; - } - - - (void)testClassifyPositiveResult { -- TFLBertNLClassifier *bertNLClassifier = -+ TFLBertNLClassifier* bertNLClassifier = - [TFLBertNLClassifier bertNLClassifierWithModelPath:self.bertModelPath]; - - XCTAssertNotNil(bertNLClassifier); - -- NSDictionary<NSString *, NSNumber *> *categories = -- [bertNLClassifier classifyWithText:@"it's a charming and often affecting journey"]; -+ NSDictionary<NSString*, NSNumber*>* categories = [bertNLClassifier -+ classifyWithText:@"it's a charming and often affecting journey"]; - - XCTAssertGreaterThan([categories[@"positive"] doubleValue], - [categories[@"negative"] doubleValue]); - } - - - (void)testClassifyNegativeResult { -- TFLBertNLClassifier *bertNLClassifier = -+ TFLBertNLClassifier* bertNLClassifier = - [TFLBertNLClassifier bertNLClassifierWithModelPath:self.bertModelPath]; - - XCTAssertNotNil(bertNLClassifier); - -- NSDictionary<NSString *, NSNumber *> *categories = -+ NSDictionary<NSString*, NSNumber*>* categories = - [bertNLClassifier classifyWithText:@"unflinchingly bleak and desperate"]; - - XCTAssertGreaterThan([categories[@"negative"] doubleValue], -@@ -62,14 +63,14 @@ NS_ASSUME_NONNULL_BEGIN - self.modelOptions = [[TFLBertNLClassifierOptions alloc] init]; - [self.modelOptions setMaxSeqLen:128]; - -- TFLBertNLClassifier *bertNLClassifier = -+ TFLBertNLClassifier* bertNLClassifier = - [TFLBertNLClassifier bertNLClassifierWithModelPath:self.bertModelPath - options:self.modelOptions]; - - XCTAssertNotNil(bertNLClassifier); - -- NSDictionary<NSString *, NSNumber *> *categories = -- [bertNLClassifier classifyWithText:@"it's a charming and often affecting journey"]; -+ NSDictionary<NSString*, NSNumber*>* categories = [bertNLClassifier -+ classifyWithText:@"it's a charming and often affecting journey"]; - - XCTAssertGreaterThan([categories[@"positive"] doubleValue], - [categories[@"negative"] doubleValue]); -@@ -79,13 +80,13 @@ NS_ASSUME_NONNULL_BEGIN - self.modelOptions = [[TFLBertNLClassifierOptions alloc] init]; - [self.modelOptions setMaxSeqLen:128]; - -- TFLBertNLClassifier *bertNLClassifier = -+ TFLBertNLClassifier* bertNLClassifier = - [TFLBertNLClassifier bertNLClassifierWithModelPath:self.bertModelPath - options:self.modelOptions]; - - XCTAssertNotNil(bertNLClassifier); - -- NSDictionary<NSString *, NSNumber *> *categories = -+ NSDictionary<NSString*, NSNumber*>* categories = - [bertNLClassifier classifyWithText:@"unflinchingly bleak and desperate"]; - - XCTAssertGreaterThan([categories[@"negative"] doubleValue], -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLNLClassifierTest.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLNLClassifierTest.m -index 40814ac6409b0..1dcf08acc8c86 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLNLClassifierTest.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLNLClassifierTest.m -@@ -19,8 +19,8 @@ limitations under the License. - NS_ASSUME_NONNULL_BEGIN - - @interface TFLNLClassifierTest : XCTestCase --@property(nonatomic, nullable) NSString *modelPath; --@property(nonatomic, nullable) TFLNLClassifierOptions *modelOptions; -+@property(nonatomic, nullable) NSString* modelPath; -+@property(nonatomic, nullable) TFLNLClassifierOptions* modelOptions; - @end - - @implementation TFLNLClassifierTest -@@ -28,34 +28,38 @@ NS_ASSUME_NONNULL_BEGIN - - - (void)setUp { - [super setUp]; -- NSBundle *bundle = [NSBundle bundleForClass:[self class]]; -- self.modelPath = [bundle pathForResource:@"test_model_nl_classifier_with_regex_tokenizer" -- ofType:@"tflite"]; -+ NSBundle* bundle = [NSBundle bundleForClass:[self class]]; -+ self.modelPath = -+ [bundle pathForResource:@"test_model_nl_classifier_with_regex_tokenizer" -+ ofType:@"tflite"]; - self.modelOptions = [[TFLNLClassifierOptions alloc] init]; - [self.modelOptions setInputTensorName:@"input_text"]; - [self.modelOptions setOutputScoreTensorName:@"probability"]; - } - - - (void)testClassifyPositiveResult { -- TFLNLClassifier *nlClassifier = [TFLNLClassifier nlClassifierWithModelPath:self.modelPath -- options:self.modelOptions]; -+ TFLNLClassifier* nlClassifier = -+ [TFLNLClassifier nlClassifierWithModelPath:self.modelPath -+ options:self.modelOptions]; - - XCTAssertNotNil(nlClassifier); - -- NSDictionary<NSString *, NSNumber *> *categories = [nlClassifier -- classifyWithText:@"This is the best movie I’ve seen in recent years. Strongly recommend it!"]; -+ NSDictionary<NSString*, NSNumber*>* categories = -+ [nlClassifier classifyWithText:@"This is the best movie I’ve seen in " -+ @"recent years. Strongly recommend it!"]; - - XCTAssertGreaterThan([categories[@"Positive"] doubleValue], - [categories[@"Negative"] doubleValue]); - } - - - (void)testClassifyNegativeResult { -- TFLNLClassifier *nlClassifier = [TFLNLClassifier nlClassifierWithModelPath:self.modelPath -- options:self.modelOptions]; -+ TFLNLClassifier* nlClassifier = -+ [TFLNLClassifier nlClassifierWithModelPath:self.modelPath -+ options:self.modelOptions]; - - XCTAssertNotNil(nlClassifier); - -- NSDictionary<NSString *, NSNumber *> *categories = -+ NSDictionary<NSString*, NSNumber*>* categories = - [nlClassifier classifyWithText:@"What a waste of my time."]; - - XCTAssertGreaterThan([categories[@"Negative"] doubleValue], diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Sources/TFLBertQuestionAnswerer.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Sources/TFLBertQuestionAnswerer.h index 57b7c69c70f62..446e2cb137dd9 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Sources/TFLBertQuestionAnswerer.h @@ -7927,139 +7763,8 @@ * @param context Context the question bases on. * @param question Question to ask. * -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Sources/TFLBertQuestionAnswerer.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Sources/TFLBertQuestionAnswerer.m -index a07f8753fbae3..b470c4643111e 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Sources/TFLBertQuestionAnswerer.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Sources/TFLBertQuestionAnswerer.m -@@ -25,7 +25,7 @@ NS_ASSUME_NONNULL_BEGIN - - @interface TFLBertQuestionAnswerer () - /** BertQuestionAnswerer backed by C API */ --@property(nonatomic) TfLiteBertQuestionAnswerer *bertQuestionAnswerer; -+@property(nonatomic) TfLiteBertQuestionAnswerer* bertQuestionAnswerer; - @end - - @implementation TFLBertQuestionAnswerer -@@ -34,14 +34,16 @@ NS_ASSUME_NONNULL_BEGIN - TfLiteBertQuestionAnswererDelete(_bertQuestionAnswerer); - } - --+ (instancetype)questionAnswererWithModelPath:(NSString *)modelPath { -- TfLiteBertQuestionAnswerer *bert_qa = TfLiteBertQuestionAnswererCreate(modelPath.UTF8String); -++ (instancetype)questionAnswererWithModelPath:(NSString*)modelPath { -+ TfLiteBertQuestionAnswerer* bert_qa = -+ TfLiteBertQuestionAnswererCreate(modelPath.UTF8String); - - _GTMDevAssert(bert_qa, @"Failed to create BertQuestionAnswerer"); - return [[TFLBertQuestionAnswerer alloc] initWithBertQuestionAnswerer:bert_qa]; - } - --- (instancetype)initWithBertQuestionAnswerer:(TfLiteBertQuestionAnswerer *)bertQuestionAnswerer { -+- (instancetype)initWithBertQuestionAnswerer: -+ (TfLiteBertQuestionAnswerer*)bertQuestionAnswerer { - self = [super init]; - if (self) { - _bertQuestionAnswerer = bertQuestionAnswerer; -@@ -49,14 +51,17 @@ NS_ASSUME_NONNULL_BEGIN - return self; - } - --- (NSArray<TFLQAAnswer *> *)answerWithContext:(NSString *)context question:(NSString *)question { -- TfLiteQaAnswers *cAnswers = TfLiteBertQuestionAnswererAnswer( -+- (NSArray<TFLQAAnswer*>*)answerWithContext:(NSString*)context -+ question:(NSString*)question { -+ TfLiteQaAnswers* cAnswers = TfLiteBertQuestionAnswererAnswer( - _bertQuestionAnswerer, context.UTF8String, question.UTF8String); -- NSMutableArray<TFLQAAnswer *> *ret = [NSMutableArray arrayWithCapacity:cAnswers->size]; -+ NSMutableArray<TFLQAAnswer*>* ret = -+ [NSMutableArray arrayWithCapacity:cAnswers->size]; - for (int i = 0; i < cAnswers->size; i++) { - TfLiteQaAnswer cAnswer = cAnswers->answers[i]; -- TFLQAAnswer *answer = [[TFLQAAnswer alloc] init]; -- struct TFLPos pos = {.start = cAnswer.start, .end = cAnswer.end, .logit = cAnswer.logit}; -+ TFLQAAnswer* answer = [[TFLQAAnswer alloc] init]; -+ struct TFLPos pos = { -+ .start = cAnswer.start, .end = cAnswer.end, .logit = cAnswer.logit}; - [answer setPos:pos]; - [answer setText:[NSString stringWithUTF8String:cAnswer.text]]; - [ret addObject:answer]; -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Tests/TFLBertQuestionAnswererTest.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Tests/TFLBertQuestionAnswererTest.m -index 9061063096cb4..ac4a1d3be63ef 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Tests/TFLBertQuestionAnswererTest.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Tests/TFLBertQuestionAnswererTest.m -@@ -16,7 +16,7 @@ limitations under the License. - - #import <XCTest/XCTest.h> - --static NSString *const kContext = -+static NSString* const kContext = - @"The role of teacher is often formal and ongoing, carried out at a school " - "or other place of formal education. In many countries, a person who " - "wishes to become a teacher must first obtain specified professional " -@@ -27,12 +27,12 @@ static NSString *const kContext = - "continuing professional development. Teachers may use a lesson plan to " - "facilitate student learning, providing a course of study which is called " - "the curriculum."; --static NSString *const kQuestion = @"What is a course of study called?"; --static NSString *const kAnswer = @"the curriculum."; -+static NSString* const kQuestion = @"What is a course of study called?"; -+static NSString* const kAnswer = @"the curriculum."; - - @interface TFLBertQuestionAnswererTest : XCTestCase --@property(nonatomic, nullable) NSString *mobileBertModelPath; --@property(nonatomic, nullable) NSString *albertModelPath; -+@property(nonatomic, nullable) NSString* mobileBertModelPath; -+@property(nonatomic, nullable) NSString* albertModelPath; - @end - - @implementation TFLBertQuestionAnswererTest -@@ -40,32 +40,33 @@ static NSString *const kAnswer = @"the curriculum."; - - - (void)setUp { - [super setUp]; -- NSBundle *bundle = [NSBundle bundleForClass:[self class]]; -- self.mobileBertModelPath = [bundle pathForResource:@"mobilebert_with_metadata" ofType:@"tflite"]; -- self.albertModelPath = [bundle pathForResource:@"albert_with_metadata" ofType:@"tflite"]; -+ NSBundle* bundle = [NSBundle bundleForClass:[self class]]; -+ self.mobileBertModelPath = [bundle pathForResource:@"mobilebert_with_metadata" -+ ofType:@"tflite"]; -+ self.albertModelPath = [bundle pathForResource:@"albert_with_metadata" -+ ofType:@"tflite"]; - } - - - (void)testInitMobileBert { -- TFLBertQuestionAnswerer* mobileBertAnswerer = -- [TFLBertQuestionAnswerer questionAnswererWithModelPath:self.mobileBertModelPath]; -+ TFLBertQuestionAnswerer* mobileBertAnswerer = [TFLBertQuestionAnswerer -+ questionAnswererWithModelPath:self.mobileBertModelPath]; - - XCTAssertNotNil(mobileBertAnswerer); - - NSArray<TFLQAAnswer*>* answers = -- [mobileBertAnswerer answerWithContext:kContext question:kQuestion]; -+ [mobileBertAnswerer answerWithContext:kContext question:kQuestion]; - - XCTAssertEqualObjects([answers[0] text], kAnswer); - } - - - (void)testInitAlbert { -- TFLBertQuestionAnswerer* albertAnswerer = -- [TFLBertQuestionAnswerer questionAnswererWithModelPath:self.albertModelPath]; -+ TFLBertQuestionAnswerer* albertAnswerer = [TFLBertQuestionAnswerer -+ questionAnswererWithModelPath:self.albertModelPath]; - - XCTAssertNotNil(albertAnswerer); - -- NSArray<TFLQAAnswer*>* answers = -- [albertAnswerer answerWithContext:kContext question:kQuestion]; -- -+ NSArray<TFLQAAnswer*>* answers = [albertAnswerer answerWithContext:kContext -+ question:kQuestion]; - - XCTAssertEqualObjects([answers[0] text], kAnswer); - } diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.h -index c37f22f3fb9aa..1b988f2be9737 100644 +index 5a161f2673632..1789508d6efda 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.h @@ -30,27 +30,29 @@ NS_ASSUME_NONNULL_BEGIN @@ -8139,648 +7844,114 @@ NS_SWIFT_NAME(classify(gmlImage:regionOfInterest:)); - (instancetype)init NS_UNAVAILABLE; -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.m -index b0a6b005b2a2d..06d6793340269 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.m -@@ -24,7 +24,7 @@ +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.h +index 64271f31b6882..38b3b0ab18ebe 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.h ++++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.h +@@ -29,27 +29,29 @@ NS_ASSUME_NONNULL_BEGIN + * Base options that is used for creation of any type of task. + * @seealso TFLBaseOptions + */ +-@property(nonatomic, copy) TFLBaseOptions *baseOptions; ++@property(nonatomic, copy) TFLBaseOptions* baseOptions; - @interface TFLImageClassifier () - /** ImageClassifier backed by C API */ --@property(nonatomic) TfLiteImageClassifier *imageClassifier; -+@property(nonatomic) TfLiteImageClassifier* imageClassifier; + /** + * Options that configure the display and filtering of results. + * @seealso TFLClassificationOptions + */ +-@property(nonatomic, copy) TFLClassificationOptions *classificationOptions; ++@property(nonatomic, copy) TFLClassificationOptions* classificationOptions; + + /** +- * Initializes TFLObjectDetectorOptions with the model path set to the specified path to a model +- * file. +- * @description The external model file, must be a single standalone TFLite file. It could be packed +- * with TFLite Model Metadata[1] and associated files if exist. Fail to provide the necessary +- * metadata and associated files might result in errors. Check the [documentation] +- * (https://www.tensorflow.org/lite/convert/metadata) for each task about the specific requirement. ++ * Initializes TFLObjectDetectorOptions with the model path set to the specified ++ * path to a model file. ++ * @description The external model file, must be a single standalone TFLite ++ * file. It could be packed with TFLite Model Metadata[1] and associated files ++ * if exist. Fail to provide the necessary metadata and associated files might ++ * result in errors. Check the [documentation] ++ * (https://www.tensorflow.org/lite/convert/metadata) for each task about the ++ * specific requirement. + * + * @param modelPath Path to a TFLite model file. + * @return An instance of TFLObjectDetectorOptions set to the specified + * modelPath. + */ +-- (nullable instancetype)initWithModelPath:(nonnull NSString *)modelPath; ++- (nullable instancetype)initWithModelPath:(nonnull NSString*)modelPath; + @end - @implementation TFLImageClassifierOptions -@@ -40,7 +40,7 @@ - return self; - } +@@ -63,20 +65,22 @@ NS_ASSUME_NONNULL_BEGIN + * + * @return A TFLObjectDetector instance. + */ +-+ (nullable instancetype)objectDetectorWithOptions:(nonnull TFLObjectDetectorOptions *)options +- error:(NSError **)error +++ (nullable instancetype)objectDetectorWithOptions: ++ (nonnull TFLObjectDetectorOptions*)options ++ error:(NSError**)error + NS_SWIFT_NAME(objectDetector(options:)); --- (nullable instancetype)initWithModelPath:(nonnull NSString *)modelPath { -+- (nullable instancetype)initWithModelPath:(nonnull NSString*)modelPath { - self = [self init]; - if (self) { - self.baseOptions.modelFile.filePath = modelPath; -@@ -55,7 +55,8 @@ - TfLiteImageClassifierDelete(_imageClassifier); - } + /** +- * Performs object detection on a GMLImage input, returns the detected objects in the image. ++ * Performs object detection on a GMLImage input, returns the detected objects ++ * in the image. + * + * @param image input to the model. + * @return Detection Result of type TFLDetectionResult an array of +- * detected objeects where each detected object has a bounding box and an array of TFLCategory +- * holding the predicted classes for the detected object. ++ * detected objeects where each detected object has a bounding box and an array ++ * of TFLCategory holding the predicted classes for the detected object. + */ +-- (nullable TFLDetectionResult *)detectWithGMLImage:(GMLImage *)image +- error:(NSError *_Nullable *)error ++- (nullable TFLDetectionResult*)detectWithGMLImage:(GMLImage*)image ++ error:(NSError* _Nullable*)error + NS_SWIFT_NAME(detect(gmlImage:)); --- (instancetype)initWithImageClassifier:(TfLiteImageClassifier *)imageClassifier { -+- (instancetype)initWithImageClassifier: -+ (TfLiteImageClassifier*)imageClassifier { - self = [super init]; - if (self) { - _imageClassifier = imageClassifier; -@@ -63,25 +64,28 @@ - return self; - } - --+ (nullable instancetype)imageClassifierWithOptions:(nonnull TFLImageClassifierOptions *)options -- error:(NSError **)error { -++ (nullable instancetype)imageClassifierWithOptions: -+ (nonnull TFLImageClassifierOptions*)options -+ error:(NSError**)error { - TfLiteImageClassifierOptions cOptions = TfLiteImageClassifierOptionsCreate(); - if (![options.classificationOptions -- copyClassificationOptionsToCClassificationOptions:&(cOptions.classification_options) -+ copyClassificationOptionsToCClassificationOptions: -+ &(cOptions.classification_options) - error:error]) - return nil; - - [options.baseOptions copyBaseOptionsToCBaseOptions:&(cOptions.base_options)]; - -- TfLiteSupportError *createClassifierError = nil; -- TfLiteImageClassifier *imageClassifier = -+ TfLiteSupportError* createClassifierError = nil; -+ TfLiteImageClassifier* imageClassifier = - TfLiteImageClassifierFromOptions(&cOptions, &createClassifierError); - -- [options.classificationOptions -- deleteCStringArraysOfClassificationOptions:&(cOptions.classification_options)]; -+ [options.classificationOptions deleteCStringArraysOfClassificationOptions: -+ &(cOptions.classification_options)]; - - if (!imageClassifier) { -- [TFLCommonUtils errorFromTfLiteSupportError:createClassifierError error:error]; -+ [TFLCommonUtils errorFromTfLiteSupportError:createClassifierError -+ error:error]; - TfLiteSupportErrorDelete(createClassifierError); - return nil; - } -@@ -89,17 +93,20 @@ - return [[TFLImageClassifier alloc] initWithImageClassifier:imageClassifier]; - } - --- (nullable TFLClassificationResult *)classifyWithGMLImage:(GMLImage *)image -- error:(NSError *_Nullable *)error { -+- (nullable TFLClassificationResult*)classifyWithGMLImage:(GMLImage*)image -+ error:(NSError* _Nullable*) -+ error { - return [self classifyWithGMLImage:image - regionOfInterest:CGRectMake(0, 0, image.width, image.height) - error:error]; - } - --- (nullable TFLClassificationResult *)classifyWithGMLImage:(GMLImage *)image -- regionOfInterest:(CGRect)roi -- error:(NSError *_Nullable *)error { -- TfLiteFrameBuffer *cFrameBuffer = [GMLImageUtils cFrameBufferFromGMLImage:image error:error]; -+- (nullable TFLClassificationResult*)classifyWithGMLImage:(GMLImage*)image -+ regionOfInterest:(CGRect)roi -+ error:(NSError* _Nullable*) -+ error { -+ TfLiteFrameBuffer* cFrameBuffer = -+ [GMLImageUtils cFrameBufferFromGMLImage:image error:error]; - - if (!cFrameBuffer) { - return nil; -@@ -110,9 +117,10 @@ - .width = roi.size.width, - .height = roi.size.height}; - -- TfLiteSupportError *classifyError = nil; -- TfLiteClassificationResult *cClassificationResult = TfLiteImageClassifierClassifyWithRoi( -- _imageClassifier, cFrameBuffer, &boundingBox, &classifyError); -+ TfLiteSupportError* classifyError = nil; -+ TfLiteClassificationResult* cClassificationResult = -+ TfLiteImageClassifierClassifyWithRoi(_imageClassifier, cFrameBuffer, -+ &boundingBox, &classifyError); - - free(cFrameBuffer->buffer); - cFrameBuffer->buffer = nil; -@@ -126,8 +134,8 @@ - return nil; - } - -- TFLClassificationResult *classificationHeadsResults = -- [TFLClassificationUtils classificationResultFromCClassificationResults:cClassificationResult]; -+ TFLClassificationResult* classificationHeadsResults = [TFLClassificationUtils -+ classificationResultFromCClassificationResults:cClassificationResult]; - TfLiteClassificationResultDelete(cClassificationResult); - - return classificationHeadsResults; + - (instancetype)init NS_UNAVAILABLE; diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.h -index 4ae67d11665b4..298485b3ceda2 100644 +index a4e6dcd5550a6..8c36e0e96cb30 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.h @@ -37,8 +37,9 @@ NS_ASSUME_NONNULL_BEGIN * @return The TfLiteFrameBuffer created from the gmlImage which can be used * with the TF Lite Task Vision C library. */ --+ (nullable TfLiteFrameBuffer *)cFrameBufferFromGMLImage:(GMLImage *)gmlImage +-+ (nullable TfLiteFrameBuffer *)cFrameBufferWithGMLImage:(GMLImage *)gmlImage - error:(NSError *_Nullable *)error; -++ (nullable TfLiteFrameBuffer*)cFrameBufferFromGMLImage:(GMLImage*)gmlImage +++ (nullable TfLiteFrameBuffer*)cFrameBufferWithGMLImage:(GMLImage*)gmlImage + error:(NSError* _Nullable*) + error; - (instancetype)init NS_UNAVAILABLE; -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.m -index 7f2a0611ce1f2..72425b39630d1 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.m -@@ -24,18 +24,20 @@ - #import <CoreVideo/CoreVideo.h> +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.h +index de9660ecd191d..8192fa131fab4 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.h ++++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.h +@@ -18,9 +18,9 @@ NS_ASSUME_NONNULL_BEGIN - @interface TFLCVPixelBufferUtils : NSObject --+ (uint8_t *_Nullable)convertBGRAtoRGBforPixelBufferBaseAddress:(CVPixelBufferRef)pixelBuffer -- error:(NSError **)error; -++ (uint8_t* _Nullable) -+ convertBGRAtoRGBforPixelBufferBaseAddress:(CVPixelBufferRef)pixelBuffer -+ error:(NSError**)error; + @interface GMLImage (Helpers) + +-+ (nullable GMLImage *)imageFromBundleWithClass:(Class)classObject +- fileName:(NSString *)name +- ofType:(NSString *)type +++ (nullable GMLImage*)imageFromBundleWithClass:(Class)classObject ++ fileName:(NSString*)name ++ ofType:(NSString*)type + NS_SWIFT_NAME(imageFromBundle(class:filename:type:)); + @end - - @interface UIImage (RawPixelDataUtils) --- (TfLiteFrameBuffer *)frameBufferWithError:(NSError **)error; -+- (TfLiteFrameBuffer*)frameBufferWithError:(NSError**)error; - @end - - @implementation TFLCVPixelBufferUtils - --+ (uint8_t *)convertBGRAtoRGBforPixelBufferBaseAddress:(CVPixelBufferRef)pixelBuffer -- error:(NSError **)error { -++ (uint8_t*)convertBGRAtoRGBforPixelBufferBaseAddress: -+ (CVPixelBufferRef)pixelBuffer -+ error:(NSError**)error { - size_t width = CVPixelBufferGetWidth(pixelBuffer); - size_t height = CVPixelBufferGetHeight(pixelBuffer); - size_t stride = CVPixelBufferGetBytesPerRow(pixelBuffer); -@@ -43,17 +45,21 @@ - int destinationChannelCount = 3; - size_t destinationBytesPerRow = destinationChannelCount * width; - -- uint8_t *pixelBufferBaseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(pixelBuffer); -+ uint8_t* pixelBufferBaseAddress = -+ (uint8_t*)CVPixelBufferGetBaseAddress(pixelBuffer); - -- uint8_t *destPixelBufferAddress = [TFLCommonUtils mallocWithSize:height * destinationBytesPerRow -- error:error]; -+ uint8_t* destPixelBufferAddress = -+ [TFLCommonUtils mallocWithSize:height * destinationBytesPerRow -+ error:error]; - - if (!destPixelBufferAddress) { - return NULL; - } - -- vImage_Buffer srcBuffer = { -- .data = pixelBufferBaseAddress, .height = height, .width = width, .rowBytes = stride}; -+ vImage_Buffer srcBuffer = {.data = pixelBufferBaseAddress, -+ .height = height, -+ .width = width, -+ .rowBytes = stride}; - - vImage_Buffer destBuffer = {.data = destPixelBufferAddress, - .height = height, -@@ -61,7 +67,8 @@ - .rowBytes = destinationBytesPerRow}; - - vImage_Error convertError = kvImageNoError; -- convertError = vImageConvert_BGRA8888toRGB888(&srcBuffer, &destBuffer, kvImageNoFlags); -+ convertError = -+ vImageConvert_BGRA8888toRGB888(&srcBuffer, &destBuffer, kvImageNoFlags); - - if (convertError != kvImageNoError) { - [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeImageProcessingError -@@ -78,8 +85,8 @@ - - @implementation UIImage (RawPixelDataUtils) - --- (TfLiteFrameBuffer *)frameBufferWithError:(NSError **)error { -- TfLiteFrameBuffer *frameBuffer = NULL; -+- (TfLiteFrameBuffer*)frameBufferWithError:(NSError**)error { -+ TfLiteFrameBuffer* frameBuffer = NULL; - - if (self.CGImage) { - frameBuffer = [self frameBufferFromCGImage:self.CGImage error:error]; -@@ -95,23 +102,25 @@ - return frameBuffer; - } - --+ (UInt8 *_Nullable)pixelDataFromCGImage:(CGImageRef)cgImage error:(NSError **)error { -++ (UInt8* _Nullable)pixelDataFromCGImage:(CGImageRef)cgImage -+ error:(NSError**)error { - long width = CGImageGetWidth(cgImage); - long height = CGImageGetHeight(cgImage); - - int bitsPerComponent = 8; -- UInt8 *buffer_to_return = NULL; -+ UInt8* buffer_to_return = NULL; - - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); -- CGContextRef context = CGBitmapContextCreate(nil, width, height, bitsPerComponent, 0, colorSpace, -- kCGImageAlphaNoneSkipLast); -+ CGContextRef context = -+ CGBitmapContextCreate(nil, width, height, bitsPerComponent, 0, colorSpace, -+ kCGImageAlphaNoneSkipLast); - - if (context) { - CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage); -- buffer_to_return = -- [UIImage populateRGBBufferFromSourceRGBABuffer:CGBitmapContextGetData(context) -- width:width -- height:height]; -+ buffer_to_return = [UIImage -+ populateRGBBufferFromSourceRGBABuffer:CGBitmapContextGetData(context) -+ width:width -+ height:height]; - CGContextRelease(context); - } - -@@ -126,15 +135,16 @@ - return buffer_to_return; - } - --+ (nullable UInt8 *)populateRGBBufferFromSourceRGBABuffer:(UInt8 *)buffer -- width:(size_t)width -- height:(size_t)height { -- if (!buffer) return nil; -++ (nullable UInt8*)populateRGBBufferFromSourceRGBABuffer:(UInt8*)buffer -+ width:(size_t)width -+ height:(size_t)height { -+ if (!buffer) -+ return nil; - - int sourceChannelCount = 4; - int destChannelCount = 3; - -- UInt8 *buffer_to_return = malloc(height * destChannelCount * width); -+ UInt8* buffer_to_return = malloc(height * destChannelCount * width); - if (!buffer_to_return) { - return nil; - } -@@ -150,14 +160,15 @@ - return buffer_to_return; - } - --- (TfLiteFrameBuffer *)frameBufferFromCGImage:(CGImageRef)cgImage error:(NSError **)error { -- UInt8 *buffer = [UIImage pixelDataFromCGImage:cgImage error:error]; -+- (TfLiteFrameBuffer*)frameBufferFromCGImage:(CGImageRef)cgImage -+ error:(NSError**)error { -+ UInt8* buffer = [UIImage pixelDataFromCGImage:cgImage error:error]; - - if (buffer == NULL) { - return NULL; - } - -- TfLiteFrameBuffer *cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); -+ TfLiteFrameBuffer* cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); - - cFrameBuffer->dimension.width = (int)CGImageGetWidth(cgImage); - cFrameBuffer->dimension.height = (int)CGImageGetHeight(cgImage); -@@ -169,14 +180,16 @@ - return cFrameBuffer; - } - --- (TfLiteFrameBuffer *)frameBufferFromCIImage:(CIImage *)ciImage error:(NSError **)error { -- uint8_t *buffer = nil; -+- (TfLiteFrameBuffer*)frameBufferFromCIImage:(CIImage*)ciImage -+ error:(NSError**)error { -+ uint8_t* buffer = nil; - - int width = 0; - int height = 0; - if (ciImage.pixelBuffer) { -- buffer = [TFLCVPixelBufferUtils convertBGRAtoRGBforPixelBufferBaseAddress:ciImage.pixelBuffer -- error:error]; -+ buffer = [TFLCVPixelBufferUtils -+ convertBGRAtoRGBforPixelBufferBaseAddress:ciImage.pixelBuffer -+ error:error]; - width = (int)CVPixelBufferGetWidth(ciImage.pixelBuffer); - height = (int)CVPixelBufferGetHeight(ciImage.pixelBuffer); - -@@ -195,7 +208,7 @@ - return NULL; - } - -- TfLiteFrameBuffer *cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); -+ TfLiteFrameBuffer* cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); - cFrameBuffer->buffer = buffer; - cFrameBuffer->dimension.width = width; - cFrameBuffer->dimension.height = height; -@@ -210,41 +223,49 @@ - - @implementation GMLImageUtils - --+ (nullable TfLiteFrameBuffer *)cFrameBufferFromGMLImage:(GMLImage *)gmlImage -- error:(NSError *_Nullable *)error { -- TfLiteFrameBuffer *cFrameBuffer = NULL; -++ (nullable TfLiteFrameBuffer*)cFrameBufferFromGMLImage:(GMLImage*)gmlImage -+ error:(NSError* _Nullable*) -+ error { -+ TfLiteFrameBuffer* cFrameBuffer = NULL; - - switch (gmlImage.imageSourceType) { - case GMLImageSourceTypeSampleBuffer: { -- CVPixelBufferRef sampleImagePixelBuffer = CMSampleBufferGetImageBuffer(gmlImage.sampleBuffer); -- cFrameBuffer = [GMLImageUtils bufferFromCVPixelBuffer:sampleImagePixelBuffer error:error]; -+ CVPixelBufferRef sampleImagePixelBuffer = -+ CMSampleBufferGetImageBuffer(gmlImage.sampleBuffer); -+ cFrameBuffer = -+ [GMLImageUtils bufferFromCVPixelBuffer:sampleImagePixelBuffer -+ error:error]; - break; - } - case GMLImageSourceTypePixelBuffer: { -- cFrameBuffer = [GMLImageUtils bufferFromCVPixelBuffer:gmlImage.pixelBuffer error:error]; -+ cFrameBuffer = [GMLImageUtils bufferFromCVPixelBuffer:gmlImage.pixelBuffer -+ error:error]; - break; - } - case GMLImageSourceTypeImage: { -- cFrameBuffer = [GMLImageUtils frameBufferFromUIImage:gmlImage.image error:error]; -+ cFrameBuffer = [GMLImageUtils frameBufferFromUIImage:gmlImage.image -+ error:error]; - } - - default: -- [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError -- description:@"Invalid source type for GMLImage." -- error:error]; -+ [TFLCommonUtils -+ customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError -+ description:@"Invalid source type for GMLImage." -+ error:error]; - break; - } - - return cFrameBuffer; - } - --+ (TfLiteFrameBuffer *)frameBufferFromUIImage:(UIImage *)image error:(NSError **)error { -++ (TfLiteFrameBuffer*)frameBufferFromUIImage:(UIImage*)image -+ error:(NSError**)error { - return [image frameBufferWithError:error]; - } - --+ (TfLiteFrameBuffer *)bufferFromCVPixelBuffer:(CVPixelBufferRef)pixelBuffer -- error:(NSError **)error { -- uint8_t *buffer = nil; -++ (TfLiteFrameBuffer*)bufferFromCVPixelBuffer:(CVPixelBufferRef)pixelBuffer -+ error:(NSError**)error { -+ uint8_t* buffer = nil; - enum TfLiteFrameBufferFormat cPixelFormat = kRGB; - - CVPixelBufferLockBaseAddress(pixelBuffer, 0); -@@ -253,25 +274,30 @@ - switch (pixelBufferFormat) { - case kCVPixelFormatType_24RGB: { - cPixelFormat = kRGB; -- buffer = [GMLImageUtils copyPixelufferDataForInference:pixelBuffer error:error]; -+ buffer = [GMLImageUtils copyPixelufferDataForInference:pixelBuffer -+ error:error]; - break; - } - case kCVPixelFormatType_32RGBA: { - cPixelFormat = kRGBA; -- buffer = [GMLImageUtils copyPixelufferDataForInference:pixelBuffer error:error]; -+ buffer = [GMLImageUtils copyPixelufferDataForInference:pixelBuffer -+ error:error]; - break; - } - case kCVPixelFormatType_32BGRA: { - cPixelFormat = kRGB; -- buffer = [TFLCVPixelBufferUtils convertBGRAtoRGBforPixelBufferBaseAddress:pixelBuffer -- error:error]; -+ buffer = [TFLCVPixelBufferUtils -+ convertBGRAtoRGBforPixelBufferBaseAddress:pixelBuffer -+ error:error]; - break; - } - - default: { -- [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError -- description:@"Unsupported pixel format for TfLiteFrameBufferFormat." -- error:error]; -+ [TFLCommonUtils -+ customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError -+ description: -+ @"Unsupported pixel format for TfLiteFrameBufferFormat." -+ error:error]; - break; - } - } -@@ -282,7 +308,7 @@ - return nil; - } - -- TfLiteFrameBuffer *cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); -+ TfLiteFrameBuffer* cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); - - cFrameBuffer->dimension.width = (int)CVPixelBufferGetWidth(pixelBuffer); - cFrameBuffer->dimension.height = (int)CVPixelBufferGetHeight(pixelBuffer); -@@ -292,12 +318,14 @@ - return cFrameBuffer; - } - --+ (UInt8 *)copyPixelufferDataForInference:(CVPixelBufferRef)pixelBuffer error:(NSError **)error { -++ (UInt8*)copyPixelufferDataForInference:(CVPixelBufferRef)pixelBuffer -+ error:(NSError**)error { - size_t height = CVPixelBufferGetHeight(pixelBuffer); - size_t stride = CVPixelBufferGetBytesPerRow(pixelBuffer); -- UInt8 *buffer = [TFLCommonUtils mallocWithSize:height * stride error:error]; -+ UInt8* buffer = [TFLCommonUtils mallocWithSize:height * stride error:error]; - -- if (buffer) memcpy(buffer, CVPixelBufferGetBaseAddress(pixelBuffer), height * stride); -+ if (buffer) -+ memcpy(buffer, CVPixelBufferGetBaseAddress(pixelBuffer), height * stride); - - return buffer; - } -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.m -index b5f514397e41d..f26959434bbc9 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.m -@@ -18,123 +18,140 @@ - NS_ASSUME_NONNULL_BEGIN - - @interface TFLImageClassifierTests : XCTestCase --@property(nonatomic, nullable) NSString *modelPath; -+@property(nonatomic, nullable) NSString* modelPath; - @end - - @implementation TFLImageClassifierTests - --- (GMLImage *)imageFromBundleWithName:(NSString *)name ofType:(NSString *)type { -- NSString *imagePath = [[NSBundle bundleForClass:[self class]] pathForResource:name ofType:type]; -+- (GMLImage*)imageFromBundleWithName:(NSString*)name ofType:(NSString*)type { -+ NSString* imagePath = -+ [[NSBundle bundleForClass:[self class]] pathForResource:name ofType:type]; - XCTAssertNotNil(imagePath); -- UIImage *image = [[UIImage alloc] initWithContentsOfFile:imagePath]; -+ UIImage* image = [[UIImage alloc] initWithContentsOfFile:imagePath]; - XCTAssertNotNil(image); - -- GMLImage *gmlImage = [[GMLImage alloc] initWithImage:image]; -+ GMLImage* gmlImage = [[GMLImage alloc] initWithImage:image]; - XCTAssertNotNil(gmlImage); - - return gmlImage; - } - - (void)setUp { -- // Put setup code here. This method is called before the invocation of each test method in the -- // class. static let bundle = Bundle(for: TFLSentencepieceTokenizerTest.self) -- self.modelPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"mobilenet_v2_1.0_224" -- ofType:@"tflite"]; -+ // Put setup code here. This method is called before the invocation of each -+ // test method in the class. static let bundle = Bundle(for: -+ // TFLSentencepieceTokenizerTest.self) -+ self.modelPath = [[NSBundle bundleForClass:[self class]] -+ pathForResource:@"mobilenet_v2_1.0_224" -+ ofType:@"tflite"]; - XCTAssertNotNil(self.modelPath); - } - - - (void)tearDown { -- // Put teardown code here. This method is called after the invocation of each test method in the -- // class. -+ // Put teardown code here. This method is called after the invocation of each -+ // test method in the class. - } - - - (void)testSuccessfullImageInferenceOnMLImageWithUIImage { -- TFLImageClassifierOptions *imageClassifierOptions = -+ TFLImageClassifierOptions* imageClassifierOptions = - [[TFLImageClassifierOptions alloc] initWithModelPath:self.modelPath]; - -- TFLImageClassifier *imageClassifier = -- [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions error:nil]; -+ TFLImageClassifier* imageClassifier = -+ [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions -+ error:nil]; - XCTAssertNotNil(imageClassifier); -- GMLImage *gmlImage = [self imageFromBundleWithName:@"burger" ofType:@"jpg"]; -+ GMLImage* gmlImage = [self imageFromBundleWithName:@"burger" ofType:@"jpg"]; - -- TFLClassificationResult *classificationResults = [imageClassifier classifyWithGMLImage:gmlImage -- error:nil]; -+ TFLClassificationResult* classificationResults = -+ [imageClassifier classifyWithGMLImage:gmlImage error:nil]; - XCTAssertTrue([classificationResults.classifications count] > 0); -- XCTAssertTrue([classificationResults.classifications[0].categories count] > 0); -+ XCTAssertTrue([classificationResults.classifications[0].categories count] > -+ 0); - -- TFLCategory *category = classificationResults.classifications[0].categories[0]; -+ TFLCategory* category = -+ classificationResults.classifications[0].categories[0]; - XCTAssertTrue([category.label isEqual:@"cheeseburger"]); - // TODO: match the score as image_classifier_test.cc - XCTAssertEqualWithAccuracy(category.score, 0.748976, 0.001); - } - - - (void)testModelOptionsWithMaxResults { -- TFLImageClassifierOptions *imageClassifierOptions = -+ TFLImageClassifierOptions* imageClassifierOptions = - [[TFLImageClassifierOptions alloc] initWithModelPath:self.modelPath]; - int maxResults = 3; - imageClassifierOptions.classificationOptions.maxResults = maxResults; - -- TFLImageClassifier *imageClassifier = -- [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions error:nil]; -+ TFLImageClassifier* imageClassifier = -+ [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions -+ error:nil]; - XCTAssertNotNil(imageClassifier); - -- GMLImage *gmlImage = [self imageFromBundleWithName:@"burger" ofType:@"jpg"]; -+ GMLImage* gmlImage = [self imageFromBundleWithName:@"burger" ofType:@"jpg"]; - -- TFLClassificationResult *classificationResults = [imageClassifier classifyWithGMLImage:gmlImage -- error:nil]; -+ TFLClassificationResult* classificationResults = -+ [imageClassifier classifyWithGMLImage:gmlImage error:nil]; - XCTAssertTrue([classificationResults.classifications count] > 0); -- XCTAssertLessThanOrEqual([classificationResults.classifications[0].categories count], maxResults); -+ XCTAssertLessThanOrEqual( -+ [classificationResults.classifications[0].categories count], maxResults); - -- TFLCategory *category = classificationResults.classifications[0].categories[0]; -+ TFLCategory* category = -+ classificationResults.classifications[0].categories[0]; - XCTAssertTrue([category.label isEqual:@"cheeseburger"]); - // TODO: match the score as image_classifier_test.cc - XCTAssertEqualWithAccuracy(category.score, 0.748976, 0.001); - } - - - (void)testInferenceWithBoundingBox { -- TFLImageClassifierOptions *imageClassifierOptions = -+ TFLImageClassifierOptions* imageClassifierOptions = - [[TFLImageClassifierOptions alloc] initWithModelPath:self.modelPath]; - int maxResults = 3; - imageClassifierOptions.classificationOptions.maxResults = maxResults; - -- TFLImageClassifier *imageClassifier = -- [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions error:nil]; -+ TFLImageClassifier* imageClassifier = -+ [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions -+ error:nil]; - XCTAssertNotNil(imageClassifier); - -- GMLImage *gmlImage = [self imageFromBundleWithName:@"multi_objects" ofType:@"jpg"]; -+ GMLImage* gmlImage = [self imageFromBundleWithName:@"multi_objects" -+ ofType:@"jpg"]; - - CGRect roi = CGRectMake(406, 110, 148, 153); -- TFLClassificationResult *classificationResults = [imageClassifier classifyWithGMLImage:gmlImage -- regionOfInterest:roi -- error:nil]; -+ TFLClassificationResult* classificationResults = -+ [imageClassifier classifyWithGMLImage:gmlImage -+ regionOfInterest:roi -+ error:nil]; - XCTAssertTrue([classificationResults.classifications count] > 0); -- XCTAssertTrue([classificationResults.classifications[0].categories count] > 0); -+ XCTAssertTrue([classificationResults.classifications[0].categories count] > -+ 0); - -- TFLCategory *category = classificationResults.classifications[0].categories[0]; -+ TFLCategory* category = -+ classificationResults.classifications[0].categories[0]; - // TODO: match the label and score as image_classifier_test.cc - // XCTAssertTrue([category.label isEqual:@"soccer ball"]); - // XCTAssertEqualWithAccuracy(category.score, 0.256512, 0.001); - } - - - (void)testInferenceWithRGBAImage { -- TFLImageClassifierOptions *imageClassifierOptions = -+ TFLImageClassifierOptions* imageClassifierOptions = - [[TFLImageClassifierOptions alloc] initWithModelPath:self.modelPath]; - -- TFLImageClassifier *imageClassifier = -- [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions error:nil]; -+ TFLImageClassifier* imageClassifier = -+ [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions -+ error:nil]; - XCTAssertNotNil(imageClassifier); - -- GMLImage *gmlImage = [self imageFromBundleWithName:@"sparrow" ofType:@"png"]; -+ GMLImage* gmlImage = [self imageFromBundleWithName:@"sparrow" ofType:@"png"]; - XCTAssertNotNil(gmlImage); - -- TFLClassificationResult *classificationResults = [imageClassifier classifyWithGMLImage:gmlImage -- error:nil]; -+ TFLClassificationResult* classificationResults = -+ [imageClassifier classifyWithGMLImage:gmlImage error:nil]; - XCTAssertTrue([classificationResults.classifications count] > 0); -- XCTAssertTrue([classificationResults.classifications[0].categories count] > 0); -+ XCTAssertTrue([classificationResults.classifications[0].categories count] > -+ 0); - -- TFLCategory *category = classificationResults.classifications[0].categories[0]; -+ TFLCategory* category = -+ classificationResults.classifications[0].categories[0]; - XCTAssertTrue([category.label isEqual:@"junco"]); -- // TODO: inspect if score is correct. Better to test againest "burger", because we know the -- // expected result for "burger.jpg". -+ // TODO: inspect if score is correct. Better to test againest "burger", -+ // because we know the expected result for "burger.jpg". - XCTAssertEqualWithAccuracy(category.score, 0.253016, 0.001); - } - diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.h -index aa6924893b301..d08f5177ceee9 100644 +index ed679c22a467b..c10c82afc1913 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.h @@ -28,11 +28,13 @@ NS_ASSUME_NONNULL_BEGIN @@ -8799,50 +7970,8 @@ + NS_DESIGNATED_INITIALIZER; @end NS_ASSUME_NONNULL_END -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.mm b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.mm -index 949cef2b0b7c2..2a028f6cd7d1a 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.mm -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.mm -@@ -24,7 +24,7 @@ using BertTokenizerCPP = ::tflite::support::text::tokenizer::BertTokenizer; - std::unique_ptr<BertTokenizerCPP> _bertTokenizer; - } - --- (instancetype)initWithVocabPath:(NSString *)vocabPath { -+- (instancetype)initWithVocabPath:(NSString*)vocabPath { - self = [super init]; - if (self) { - _bertTokenizer = absl::make_unique<BertTokenizerCPP>(MakeString(vocabPath)); -@@ -32,12 +32,12 @@ using BertTokenizerCPP = ::tflite::support::text::tokenizer::BertTokenizer; - return self; - } - --- (instancetype)initWithVocab:(NSArray<NSString *> *)vocab { -+- (instancetype)initWithVocab:(NSArray<NSString*>*)vocab { - self = [super init]; - if (self) { - std::vector<std::string> vocabCpp; - vocabCpp.reserve([vocab count]); -- for (NSString *word in vocab) { -+ for (NSString* word in vocab) { - vocabCpp.emplace_back(MakeString(word)); - } - _bertTokenizer = absl::make_unique<BertTokenizerCPP>(vocabCpp); -@@ -45,11 +45,11 @@ using BertTokenizerCPP = ::tflite::support::text::tokenizer::BertTokenizer; - return self; - } - --- (NSArray<NSString *> *)tokensFromInput:(NSString *)input { -+- (NSArray<NSString*>*)tokensFromInput:(NSString*)input { - return Tokenize(_bertTokenizer.get(), input); - } - --- (NSArray<NSNumber *> *)idsFromTokens:(NSArray<NSString *> *)tokens { -+- (NSArray<NSNumber*>*)idsFromTokens:(NSArray<NSString*>*)tokens { - return ConvertTokensToIds(_bertTokenizer.get(), tokens); - } - diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.h -index eef3bf1e223e6..9813e32ecb5d3 100644 +index f556dc642d736..be4010abd8e6f 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.h @@ -28,6 +28,6 @@ NS_ASSUME_NONNULL_BEGIN @@ -8853,43 +7982,6 @@ +- (instancetype)initWithModelPath:(NSString*)modelPath; @end NS_ASSUME_NONNULL_END -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.mm b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.mm -index 1e21cee5c08d2..1ba49923040c1 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.mm -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.mm -@@ -19,25 +19,27 @@ limitations under the License. - #import "third_party/tensorflow_lite_support/ios/utils/Sources/TFLStringUtil.h" - - NS_ASSUME_NONNULL_BEGIN --using SentencepieceTokenizerCPP = ::tflite::support::text::tokenizer::SentencePieceTokenizer; -+using SentencepieceTokenizerCPP = -+ ::tflite::support::text::tokenizer::SentencePieceTokenizer; - - @implementation TFLSentencepieceTokenizer { - std::unique_ptr<SentencepieceTokenizerCPP> _spTokenizer; - } - --- (instancetype)initWithModelPath:(NSString *)modelPath { -+- (instancetype)initWithModelPath:(NSString*)modelPath { - self = [super init]; - if (self) { -- _spTokenizer = absl::make_unique<SentencepieceTokenizerCPP>(MakeString(modelPath)); -+ _spTokenizer = -+ absl::make_unique<SentencepieceTokenizerCPP>(MakeString(modelPath)); - } - return self; - } - --- (NSArray<NSString *> *)tokensFromInput:(NSString *)input { -+- (NSArray<NSString*>*)tokensFromInput:(NSString*)input { - return Tokenize(_spTokenizer.get(), input); - } - --- (NSArray<NSNumber *> *)idsFromTokens:(NSArray<NSString *> *)tokens { -+- (NSArray<NSNumber*>*)idsFromTokens:(NSArray<NSString*>*)tokens { - return ConvertTokensToIds(_spTokenizer.get(), tokens); - } - diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizer.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizer.h index ee0972f8aba30..bd832060b6e80 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizer.h @@ -8944,41 +8036,6 @@ -NSArray<NSNumber *> *ConvertTokensToIds(Tokenizer *tokenizer, NSArray<NSString *> *tokens); +NSArray<NSNumber*>* ConvertTokensToIds(Tokenizer* tokenizer, + NSArray<NSString*>* tokens); -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizerUtil.mm b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizerUtil.mm -index 52180578170d8..8e92e3712e29e 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizerUtil.mm -+++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizerUtil.mm -@@ -18,21 +18,24 @@ limitations under the License. - - using ::tflite::support::text::tokenizer::TokenizerResult; - --NSArray<NSString *> *Tokenize(Tokenizer *tokenizer, NSString *input) { -+NSArray<NSString*>* Tokenize(Tokenizer* tokenizer, NSString* input) { - TokenizerResult tokenize_result = tokenizer->Tokenize(MakeString(input)); - std::vector<std::string> subwords = tokenize_result.subwords; -- NSMutableArray<NSString *> *ret = [NSMutableArray arrayWithCapacity:subwords.size()]; -+ NSMutableArray<NSString*>* ret = -+ [NSMutableArray arrayWithCapacity:subwords.size()]; - for (int i = 0; i < subwords.size(); ++i) { - [ret addObject:MakeNSString(subwords[i])]; - } - return ret; - } - --NSArray<NSNumber *> *ConvertTokensToIds(Tokenizer *tokenizer, NSArray<NSString *> *tokens) { -- NSMutableArray<NSNumber *> *ret = [NSMutableArray arrayWithCapacity:[tokens count]]; -- for (NSString *token in tokens) { -+NSArray<NSNumber*>* ConvertTokensToIds(Tokenizer* tokenizer, -+ NSArray<NSString*>* tokens) { -+ NSMutableArray<NSNumber*>* ret = -+ [NSMutableArray arrayWithCapacity:[tokens count]]; -+ for (NSString* token in tokens) { - std::string cc_token = MakeString(token); -- const char *cToken = cc_token.c_str(); -+ const char* cToken = cc_token.c_str(); - int id; - tokenizer->LookupId(cToken, &id); - [ret addObject:[NSNumber numberWithInt:id]]; diff --git a/third_party/tflite_support/src/tensorflow_lite_support/java/src/java/org/tensorflow/lite/support/audio/TensorAudio.java b/third_party/tflite_support/src/tensorflow_lite_support/java/src/java/org/tensorflow/lite/support/audio/TensorAudio.java index 1d8a9767f41c7..e066146eb0c7d 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/java/src/java/org/tensorflow/lite/support/audio/TensorAudio.java @@ -15601,7 +14658,7 @@ + } } diff --git a/third_party/tflite_support/src/tensorflow_lite_support/java/src/java/org/tensorflow/lite/support/model/Model.java b/third_party/tflite_support/src/tensorflow_lite_support/java/src/java/org/tensorflow/lite/support/model/Model.java -index 1c37c1b3d800d..af2061e948970 100644 +index 09b63f1b12beb..282f2b9aa599c 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/java/src/java/org/tensorflow/lite/support/model/Model.java +++ b/third_party/tflite_support/src/tensorflow_lite_support/java/src/java/org/tensorflow/lite/support/model/Model.java @@ -16,9 +16,7 @@ limitations under the License. @@ -15626,7 +14683,7 @@ /** * The wrapper class for a TFLite model and a TFLite interpreter. * -@@ -34,253 +36,244 @@ import org.tensorflow.lite.support.common.internal.SupportPreconditions; +@@ -34,263 +36,254 @@ import org.tensorflow.lite.support.common.internal.SupportPreconditions; * interpreter instance to run it. */ public class Model { @@ -15654,11 +14711,13 @@ - public static class Options { - private final Device device; - private final int numThreads; +- private final TfLiteRuntime tfLiteRuntime; - - /** Builder of {@link Options}. See its doc for details. */ - public static class Builder { - private Device device = Device.CPU; - private int numThreads = 1; +- private TfLiteRuntime tfLiteRuntime; - - public Builder setDevice(Device device) { - this.device = device; @@ -15670,6 +14729,11 @@ - return this; - } - +- public Builder setTfLiteRuntime(TfLiteRuntime tfLiteRuntime) { +- this.tfLiteRuntime = tfLiteRuntime; +- return this; +- } +- - public Options build() { - return new Options(this); - } @@ -15686,11 +14750,13 @@ + public static class Options { + private final Device device; + private final int numThreads; ++ private final TfLiteRuntime tfLiteRuntime; + + /** Builder of {@link Options}. See its doc for details. */ + public static class Builder { + private Device device = Device.CPU; + private int numThreads = 1; ++ private TfLiteRuntime tfLiteRuntime; + + public Builder setDevice(Device device) { + this.device = device; @@ -15702,6 +14768,11 @@ + return this; + } + ++ public Builder setTfLiteRuntime(TfLiteRuntime tfLiteRuntime) { ++ this.tfLiteRuntime = tfLiteRuntime; ++ return this; ++ } ++ + public Options build() { + return new Options(this); + } @@ -15710,12 +14781,14 @@ + private Options(Builder builder) { + device = builder.device; + numThreads = builder.numThreads; ++ tfLiteRuntime = builder.tfLiteRuntime; + } } - private Options(Builder builder) { - device = builder.device; - numThreads = builder.numThreads; +- tfLiteRuntime = builder.tfLiteRuntime; - } - } + /** An instance of the driver class to run model inference with Tensorflow Lite. */ @@ -15755,7 +14828,6 @@ + * @param modelPath Asset path of the model (.tflite file). + * @throws IOException if an I/O error occurs when loading the tflite model. + */ -+ @NonNull + public Builder(@NonNull Context context, @NonNull String modelPath) throws IOException { + this.modelPath = modelPath; + byteModel = FileUtil.loadMappedFile(context, modelPath); @@ -15823,7 +14895,6 @@ + * @param options The options for running the model. + * @throws IOException if any exception occurs when open the model file. */ -- @NonNull - public Builder(@NonNull Context context, @NonNull String modelPath) throws IOException { - this.modelPath = modelPath; - byteModel = FileUtil.loadMappedFile(context, modelPath); @@ -15869,7 +14940,10 @@ + break; + } + interpreterOptions.setNumThreads(options.numThreads); -+ InterpreterApi interpreter = new InterpreterFactory().create(byteModel, interpreterOptions); ++ if (options.tfLiteRuntime != null) { ++ interpreterOptions.setRuntime(options.tfLiteRuntime); ++ } ++ InterpreterApi interpreter = InterpreterApi.create(byteModel, interpreterOptions); + return new Model(modelPath, byteModel, interpreter, gpuDelegateProxy); } @@ -15892,24 +14966,6 @@ - return createModel(byteModel, modelPath, options); + public String getPath() { + return modelPath; -+ } -+ -+ /** -+ * Gets the Tensor associated with the provided input index. -+ * -+ * @throws IllegalStateException if the interpreter is closed. -+ */ -+ public Tensor getInputTensor(int inputIndex) { -+ return interpreter.getInputTensor(inputIndex); -+ } -+ -+ /** -+ * Gets the Tensor associated with the provided output index. -+ * -+ * @throws IllegalStateException if the interpreter is closed. -+ */ -+ public Tensor getOutputTensor(int outputIndex) { -+ return interpreter.getOutputTensor(outputIndex); } - } - @@ -15975,15 +15031,26 @@ - break; + + /** -+ * Returns the output shape. Useful if output shape is only determined when graph is created. ++ * Gets the Tensor associated with the provided input index. + * + * @throws IllegalStateException if the interpreter is closed. + */ -+ public int[] getOutputTensorShape(int outputIndex) { -+ return interpreter.getOutputTensor(outputIndex).shape(); ++ public Tensor getInputTensor(int inputIndex) { ++ return interpreter.getInputTensor(inputIndex); } - interpreterOptions.setNumThreads(options.numThreads); -- InterpreterApi interpreter = new InterpreterFactory().create(byteModel, interpreterOptions); +- if (options.tfLiteRuntime != null) { +- interpreterOptions.setRuntime(options.tfLiteRuntime); ++ ++ /** ++ * Gets the Tensor associated with the provided output index. ++ * ++ * @throws IllegalStateException if the interpreter is closed. ++ */ ++ public Tensor getOutputTensor(int outputIndex) { ++ return interpreter.getOutputTensor(outputIndex); + } +- InterpreterApi interpreter = InterpreterApi.create(byteModel, interpreterOptions); - return new Model(modelPath, byteModel, interpreter, gpuDelegateProxy); - } - @@ -16048,6 +15115,15 @@ - interpreter.close(); + + /** ++ * Returns the output shape. Useful if output shape is only determined when graph is created. ++ * ++ * @throws IllegalStateException if the interpreter is closed. ++ */ ++ public int[] getOutputTensorShape(int outputIndex) { ++ return interpreter.getOutputTensor(outputIndex).shape(); ++ } ++ ++ /** + * Runs model inference on multiple inputs, and returns multiple outputs. + * + * @param inputs an array of input data. The inputs should be in the same order as inputs of the @@ -34396,18 +33472,20 @@ // The unpacked model FlatBuffer. tflite::ModelT model_t_; diff --git a/third_party/tflite_support/src/tensorflow_lite_support/metadata/cc/metadata_version.cc b/third_party/tflite_support/src/tensorflow_lite_support/metadata/cc/metadata_version.cc -index fb3e01e00b76d..ed75b656e70a2 100644 +index fb3e01e00b76d..2e2f2fa070362 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/metadata/cc/metadata_version.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/metadata/cc/metadata_version.cc -@@ -22,7 +22,7 @@ limitations under the License. +@@ -22,8 +22,8 @@ limitations under the License. #include <string> #include <vector> -#include "absl/strings/str_join.h" // from @com_google_absl -+#include "absl/strings/str_join.h" // from @com_google_absl - #include "absl/strings/str_split.h" // from @com_google_absl +-#include "absl/strings/str_split.h" // from @com_google_absl ++#include "absl/strings/str_join.h" // from @com_google_absl ++#include "absl/strings/str_split.h" // from @com_google_absl #include "flatbuffers/flatbuffers.h" // from @flatbuffers #include "tensorflow/lite/c/common.h" + #include "tensorflow/lite/kernels/internal/compatibility.h" @@ -134,7 +134,8 @@ template <typename T> void UpdateMinimumVersionForArray( const flatbuffers::Vector<flatbuffers::Offset<T>>* array, @@ -40589,7 +39667,7 @@ + } } diff --git a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/apis/GMLImage.h b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/apis/GMLImage.h -index 110186bb63a1b..0c494915e7357 100644 +index 110186bb63a1b..18797d8135eb8 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/apis/GMLImage.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/apis/GMLImage.h @@ -19,7 +19,8 @@ @@ -40597,8 +39675,8 @@ /** Types of image sources. */ -typedef NSInteger GMLImageSourceType NS_TYPED_ENUM NS_SWIFT_NAME(MLImageSourceType); -+typedef NSInteger GMLImageSourceType NS_TYPED_ENUM -+ NS_SWIFT_NAME(MLImageSourceType); ++typedef NSInteger GMLImageSourceType ++ NS_TYPED_ENUM NS_SWIFT_NAME(MLImageSourceType); /** Image source is a `UIImage`. */ static const GMLImageSourceType GMLImageSourceTypeImage = 0; /** Image source is a `CVPixelBuffer`. */ @@ -40680,202 +39758,6 @@ */ - (nullable instancetype)initWithSampleBuffer:(CMSampleBufferRef)sampleBuffer NS_DESIGNATED_INITIALIZER; -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/sources/GMLImage.m b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/sources/GMLImage.m -index 094d4e01377d2..38ca74268acc1 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/sources/GMLImage.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/sources/GMLImage.m -@@ -20,7 +20,7 @@ NS_ASSUME_NONNULL_BEGIN - - #pragma mark - Public - --- (nullable instancetype)initWithImage:(UIImage *)image { -+- (nullable instancetype)initWithImage:(UIImage*)image { - if (image.CGImage == NULL) { - return nil; - } -diff --git a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/tests/GMLImageTests.m b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/tests/GMLImageTests.m -index 59205747e416a..8abee1ab2f171 100644 ---- a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/tests/GMLImageTests.m -+++ b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/tests/GMLImageTests.m -@@ -22,8 +22,8 @@ - - NS_ASSUME_NONNULL_BEGIN - --static NSString *const kTestImageName = @"grace_hopper"; --static NSString *const kTestImageType = @"jpg"; -+static NSString* const kTestImageName = @"grace_hopper"; -+static NSString* const kTestImageType = @"jpg"; - static CGFloat kTestImageWidthInPixels = 517.0f; - static CGFloat kTestImageHeightInPixels = 606.0f; - -@@ -31,7 +31,7 @@ static CGFloat kTestImageHeightInPixels = 606.0f; - @interface GMLImageTests : XCTestCase - - /** Test image. */ --@property(nonatomic, nullable) UIImage *image; -+@property(nonatomic, nullable) UIImage* image; - - @end - -@@ -41,8 +41,9 @@ static CGFloat kTestImageHeightInPixels = 606.0f; - - - (void)setUp { - [super setUp]; -- NSString *imageName = [[NSBundle bundleForClass:[self class]] pathForResource:kTestImageName -- ofType:kTestImageType]; -+ NSString* imageName = -+ [[NSBundle bundleForClass:[self class]] pathForResource:kTestImageName -+ ofType:kTestImageType]; - self.image = [[UIImage alloc] initWithContentsOfFile:imageName]; - } - -@@ -52,53 +53,59 @@ static CGFloat kTestImageHeightInPixels = 606.0f; - } - - - (void)testInitWithImage { -- GMLImage *mlImage = [[GMLImage alloc] initWithImage:self.image]; -+ GMLImage* mlImage = [[GMLImage alloc] initWithImage:self.image]; - XCTAssertNotNil(mlImage); - XCTAssertEqual(mlImage.imageSourceType, GMLImageSourceTypeImage); - XCTAssertEqual(mlImage.orientation, self.image.imageOrientation); - mlImage.orientation = UIImageOrientationDown; - XCTAssertEqual(mlImage.orientation, UIImageOrientationDown); -- XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, FLT_EPSILON); -- XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, FLT_EPSILON); -+ XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, -+ FLT_EPSILON); -+ XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, -+ FLT_EPSILON); - } - - - (void)testInitWithImage_nilImage { -- GMLImage *mlImage = [[GMLImage alloc] initWithImage:nil]; -+ GMLImage* mlImage = [[GMLImage alloc] initWithImage:nil]; - XCTAssertNil(mlImage); - } - - - (void)testInitWithSampleBuffer { - CMSampleBufferRef sampleBuffer = [self sampleBuffer]; -- GMLImage *mlImage = [[GMLImage alloc] initWithSampleBuffer:sampleBuffer]; -+ GMLImage* mlImage = [[GMLImage alloc] initWithSampleBuffer:sampleBuffer]; - XCTAssertNotNil(mlImage); - XCTAssertEqual(mlImage.imageSourceType, GMLImageSourceTypeSampleBuffer); - XCTAssertEqual(mlImage.orientation, UIImageOrientationUp); - mlImage.orientation = UIImageOrientationDown; - XCTAssertEqual(mlImage.orientation, UIImageOrientationDown); -- XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, FLT_EPSILON); -- XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, FLT_EPSILON); -+ XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, -+ FLT_EPSILON); -+ XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, -+ FLT_EPSILON); - } - - - (void)testInitWithSampleBuffer_nilImage { -- GMLImage *mlImage = [[GMLImage alloc] initWithSampleBuffer:nil]; -+ GMLImage* mlImage = [[GMLImage alloc] initWithSampleBuffer:nil]; - XCTAssertNil(mlImage); - } - - - (void)testInitWithPixelBuffer { - CMSampleBufferRef sampleBuffer = [self sampleBuffer]; - CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); -- GMLImage *mlImage = [[GMLImage alloc] initWithPixelBuffer:pixelBuffer]; -+ GMLImage* mlImage = [[GMLImage alloc] initWithPixelBuffer:pixelBuffer]; - XCTAssertNotNil(mlImage); - XCTAssertEqual(mlImage.imageSourceType, GMLImageSourceTypePixelBuffer); - XCTAssertEqual(mlImage.orientation, UIImageOrientationUp); - mlImage.orientation = UIImageOrientationDown; - XCTAssertEqual(mlImage.orientation, UIImageOrientationDown); -- XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, FLT_EPSILON); -- XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, FLT_EPSILON); -+ XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, -+ FLT_EPSILON); -+ XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, -+ FLT_EPSILON); - } - - - (void)testInitWithPixelBuffer_nilImage { -- GMLImage *mlImage = [[GMLImage alloc] initWithPixelBuffer:nil]; -+ GMLImage* mlImage = [[GMLImage alloc] initWithPixelBuffer:nil]; - XCTAssertNil(mlImage); - } - -@@ -117,17 +124,18 @@ static CGFloat kTestImageHeightInPixels = 606.0f; - size_t bpr = CGImageGetBytesPerRow(CGImage); - - CGDataProviderRef provider = CGImageGetDataProvider(CGImage); -- NSData *imageRGBAData = (id)CFBridgingRelease(CGDataProviderCopyData(provider)); -+ NSData* imageRGBAData = -+ (id)CFBridgingRelease(CGDataProviderCopyData(provider)); - const uint8_t order[4] = {2, 1, 0, 3}; - -- NSData *imageBGRAData = nil; -- unsigned char *bgraPixel = (unsigned char *)malloc([imageRGBAData length]); -+ NSData* imageBGRAData = nil; -+ unsigned char* bgraPixel = (unsigned char*)malloc([imageRGBAData length]); - if (bgraPixel) { - vImage_Buffer src; - src.height = height; - src.width = width; - src.rowBytes = bpr; -- src.data = (void *)[imageRGBAData bytes]; -+ src.data = (void*)[imageRGBAData bytes]; - - vImage_Buffer dest; - dest.height = height; -@@ -136,11 +144,13 @@ static CGFloat kTestImageHeightInPixels = 606.0f; - dest.data = bgraPixel; - - // Specify ordering changes in map. -- vImage_Error error = vImagePermuteChannels_ARGB8888(&src, &dest, order, kvImageNoFlags); -+ vImage_Error error = -+ vImagePermuteChannels_ARGB8888(&src, &dest, order, kvImageNoFlags); - - // Package the result. - if (error == kvImageNoError) { -- imageBGRAData = [NSData dataWithBytes:bgraPixel length:[imageRGBAData length]]; -+ imageBGRAData = [NSData dataWithBytes:bgraPixel -+ length:[imageRGBAData length]]; - } - - // Memory cleanup. -@@ -152,14 +162,15 @@ static CGFloat kTestImageHeightInPixels = 606.0f; - } - - // Write data to `CMSampleBuffer`. -- NSDictionary *options = @{ -- (__bridge NSString *)kCVPixelBufferCGImageCompatibilityKey : @(YES), -- (__bridge NSString *)kCVPixelBufferCGBitmapContextCompatibilityKey : @(YES) -+ NSDictionary* options = @{ -+ (__bridge NSString*)kCVPixelBufferCGImageCompatibilityKey : @(YES), -+ (__bridge NSString*)kCVPixelBufferCGBitmapContextCompatibilityKey : @(YES) - }; - CVPixelBufferRef pixelBuffer; - CVReturn status = CVPixelBufferCreateWithBytes( -- kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA, (void *)[imageBGRAData bytes], -- bpr, NULL, nil, (__bridge CFDictionaryRef)options, &pixelBuffer); -+ kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA, -+ (void*)[imageBGRAData bytes], bpr, NULL, nil, -+ (__bridge CFDictionaryRef)options, &pixelBuffer); - - if (status != kCVReturnSuccess) { - XCTFail(@"Failed to create pixel buffer."); -@@ -167,10 +178,12 @@ static CGFloat kTestImageHeightInPixels = 606.0f; - - CVPixelBufferLockBaseAddress(pixelBuffer, 0); - CMVideoFormatDescriptionRef videoInfo = NULL; -- CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, &videoInfo); -+ CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, -+ &videoInfo); - - CMSampleBufferRef buffer; -- CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, true, NULL, NULL, videoInfo, -+ CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, true, -+ NULL, NULL, videoInfo, - &kCMTimingInfoInvalid, &buffer); - - CVPixelBufferUnlockBaseAddress(pixelBuffer, 0); diff --git a/third_party/tflite_support/src/tensorflow_lite_support/odml/java/image/src/com/google/android/odml/image/BitmapExtractor.java b/third_party/tflite_support/src/tensorflow_lite_support/odml/java/image/src/com/google/android/odml/image/BitmapExtractor.java index a32fc24749e0c..59116a72a0533 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/odml/java/image/src/com/google/android/odml/image/BitmapExtractor.java @@ -42292,7 +41174,7 @@ + } } diff --git a/third_party/tflite_support/src/tensorflow_lite_support/odml/java/image/src/com/google/android/odml/image/MlImage.java b/third_party/tflite_support/src/tensorflow_lite_support/odml/java/image/src/com/google/android/odml/image/MlImage.java -index 975ff7c0908c7..7e21e6ad428f2 100644 +index 2ed3539de67f5..7e21e6ad428f2 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/odml/java/image/src/com/google/android/odml/image/MlImage.java +++ b/third_party/tflite_support/src/tensorflow_lite_support/odml/java/image/src/com/google/android/odml/image/MlImage.java @@ -16,9 +16,12 @@ limitations under the License. @@ -42447,7 +41329,7 @@ - - /** Returns the timestamp attached to the image. */ - long getTimestamp() { -- return timestamp; +- return timestamp; - } - - /** Returns the width of the image. */ @@ -43792,6 +42674,328 @@ + // Should not be instantiated. + private TestImageCreator() {} } +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common.sh b/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common.sh +index 135e4286275f1..17c38d288a25a 100644 +--- a/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common.sh ++++ b/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common.sh +@@ -1,95 +1,90 @@ +-#!/usr/bin/env bash +-# Copyright 2020 The TensorFlow Authors. All Rights Reserved. ++#!/ usr / bin / env bash ++#Copyright 2020 The TensorFlow Authors.All Rights Reserved. + # +-# Licensed under the Apache License, Version 2.0 (the "License"); +-# you may not use this file except in compliance with the License. +-# You may obtain a copy of the License at ++#Licensed under the Apache License, Version 2.0(the "License"); ++#you may not use this file except in compliance with the License. ++#You may obtain a copy of the License at + # +-# http://www.apache.org/licenses/LICENSE-2.0 ++#http: // www.apache.org/licenses/LICENSE-2.0 + # +-# Unless required by applicable law or agreed to in writing, software +-# distributed under the License is distributed on an "AS IS" BASIS, +-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-# See the License for the specific language governing permissions and +-# limitations under the License. +-# ============================================================================== +-# External `common.sh` ++#Unless required by applicable law or agreed to in writing, software ++#distributed under the License is distributed on an "AS IS" BASIS, ++#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++#See the License for the specific language governing permissions and ++#limitations under the License. ++#== == == == == == == == == == == == == == == == == == == == == == == == == == \ ++ == == == == == == == == == == == == == ++#External `common.sh` + +-# Keep in sync with tensorflow core and configure.py. +-LATEST_BAZEL_VERSION=4.2.2 +- +-# Run flaky functions with retries. +-# run_with_retry cmd +-function run_with_retry { ++#Keep in sync with tensorflow core and configure.py. ++LATEST_BAZEL_VERSION = 4.2.2 ++#Run flaky functions with retries. ++#run_with_retry cmd ++ function run_with_retry { + eval "$1" +- # If the command fails retry again in 60 seconds. +- if [[ $? -ne 0 ]]; then +- sleep 60 +- eval "$1" +- fi ++#If the command fails retry again in 60 seconds. ++ if [[ $? -ne 0 ]]; ++ then sleep 60 eval "$1" fi + } + + function die() { +- echo "$@" 1>&2 ; exit 1; ++ echo "$@" 1 > &2; ++ exit 1; + } + +-# A small utility to run the command and only print logs if the command fails. +-# On success, all logs are hidden. +-function readable_run { +- # Disable debug mode to avoid printing of variables here. +- set +x +- result=$("$@" 2>&1) || die "$result" +- echo "$@" +- echo "Command completed successfully at $(date)" +- set -x +-} ++#A small utility to run the command and only print logs if the command fails. ++#On success, all logs are hidden. ++function readable_run{ ++#Disable debug mode to avoid printing of variables here. ++ set + x result = ++ $("$@" 2 > &1) || die "$result" echo "$@" echo ++ "Command completed successfully at $(date)" set - ++ x} + +-# TODO(b/158448780): Guard bazel installation with IfChangeThenChange. +-function set_bazel_outdir { +- mkdir -p /tmpfs/bazel_output +- export TEST_TMPDIR=/tmpfs/bazel_output +-} ++#TODO(b / 158448780) : Guard bazel installation with IfChangeThenChange. ++function set_bazel_outdir{mkdir - p / tmpfs / bazel_output export TEST_TMPDIR = ++ / tmpfs / bazel_output} + +-# Downloads bazelisk to ~/bin as `bazel`. ++#Downloads bazelisk to ~ / bin as `bazel`. + function install_bazelisk { + date + case "$(uname -s)" in +- Darwin) local name=bazelisk-darwin-amd64 ;; +- Linux) local name=bazelisk-linux-amd64 ;; +- *) die "Unknown OS: $(uname -s)" ;; +- esac +- mkdir -p "$HOME/bin" +- wget --no-verbose -O "$HOME/bin/bazel" \ +- "https://github.com/bazelbuild/bazelisk/releases/download/v1.3.0/$name" +- chmod u+x "$HOME/bin/bazel" +- if [[ ! ":$PATH:" =~ :"$HOME"/bin/?: ]]; then +- PATH="$HOME/bin:$PATH" +- fi +- set_bazel_outdir +- which bazel +- bazel version +- date ++ Darwin) local name=bazelisk-darwin-amd64 ; ++ ; ++ Linux) local name=bazelisk-linux-amd64 ; ++ ; ++ *) die "Unknown OS: $(uname -s)" ; ++ ; ++ esac mkdir - p "$HOME/bin" wget-- no - verbose - ++ O ++ "$HOME/bin/bazel" ++ "https://github.com/bazelbuild/bazelisk/releases/download/v1.3.0/" ++ "$name" chmod u + ++ x "$HOME/bin/bazel" if[[!":$PATH:" = ~:"$HOME" / bin / ?: ]]; ++ then PATH = ++ "$HOME/bin:$PATH" fi set_bazel_outdir which bazel bazel version date + } + +-# Install the given bazel version on linux ++#Install the given bazel version on linux + function update_bazel_linux { +- if [[ -z "$1" ]]; then +- BAZEL_VERSION=${LATEST_BAZEL_VERSION} +- else +- BAZEL_VERSION=$1 +- fi +- rm -rf ~/bazel +- mkdir ~/bazel ++ if ++ [[-z "$1"]]; ++ then BAZEL_VERSION = $ { ++ LATEST_BAZEL_VERSION ++ } ++ else BAZEL_VERSION = ++ $1 fi rm - ++ rf ~ / bazel mkdir ~ / ++ bazel + +- pushd ~/bazel +- readable_run wget https://github.com/bazelbuild/bazel/releases/download/"${BAZEL_VERSION}"/bazel-"${BAZEL_VERSION}"-installer-linux-x86_64.sh +- chmod +x bazel-*.sh +- ./bazel-"${BAZEL_VERSION}"-installer-linux-x86_64.sh --user +- rm bazel-"${BAZEL_VERSION}"-installer-linux-x86_64.sh +- popd ++ pushd ~ / ++ bazel readable_run wget https ++ : // github.com/bazelbuild/bazel/releases/download/"${BAZEL_VERSION}"/bazel-"${BAZEL_VERSION}"-installer-linux-x86_64.sh ++ chmod + ++ x bazel - *.sh./ bazel - "${BAZEL_VERSION}" - installer - linux - ++ x86_64.sh-- user rm bazel - "${BAZEL_VERSION}" - installer - linux - ++ x86_64.sh popd + +- PATH="/home/kbuilder/bin:$PATH" +- set_bazel_outdir +- which bazel +- bazel version ++ PATH = ++ "/home/kbuilder/bin:$PATH" set_bazel_outdir which bazel bazel version + } +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh +old mode 100755 +new mode 100644 +index 5580f4a7c7045..e2ad7acc54606 +--- a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh ++++ b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh +@@ -1,24 +1,37 @@ +-#!/usr/bin/env bash +-# Copyright 2021 The TensorFlow Authors. All Rights Reserved. ++#!/ usr / bin / env bash ++#Copyright 2021 The TensorFlow Authors.All Rights Reserved. + # +-# Licensed under the Apache License, Version 2.0 (the "License"); +-# you may not use this file except in compliance with the License. +-# You may obtain a copy of the License at ++#Licensed under the Apache License, Version 2.0(the "License"); ++#you may not use this file except in compliance with the License. ++#You may obtain a copy of the License at + # +-# http://www.apache.org/licenses/LICENSE-2.0 ++#http: // www.apache.org/licenses/LICENSE-2.0 + # +-# Unless required by applicable law or agreed to in writing, software +-# distributed under the License is distributed on an "AS IS" BASIS, +-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-# See the License for the specific language governing permissions and +-# limitations under the License. +-# ============================================================================== ++#Unless required by applicable law or agreed to in writing, software ++#distributed under the License is distributed on an "AS IS" BASIS, ++#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++#See the License for the specific language governing permissions and ++#limitations under the License. ++#== == == == == == == == == == == == == == == == == == == == == == == == == == \ ++ == == == == == == == == == == == == == + +-set -ex ++set - ex + +-NIGHTLY_FLAG=$1 ++ NIGHTLY_FLAG = ++ $1 + +-bazel build -c opt --config=elinux_armhf tensorflow_lite_support/tools/pip_package:build_pip_package +-EXTRA_PKG_NAME_FLAG="--plat-name=manylinux2014-armv7l" ./bazel-bin/tensorflow_lite_support/tools/pip_package/build_pip_package --dst wheels ${NIGHTLY_FLAG} +-bazel build -c opt --config=elinux_aarch64 tensorflow_lite_support/tools/pip_package:build_pip_package +-EXTRA_PKG_NAME_FLAG="--plat-name=manylinux2014-aarch64" ./bazel-bin/tensorflow_lite_support/tools/pip_package/build_pip_package --dst wheels ${NIGHTLY_FLAG} ++ bazel build - ++ c opt-- config = ++ elinux_armhf tensorflow_lite_support / tools / ++ pip_package : build_pip_package EXTRA_PKG_NAME_FLAG = ++ "--plat-name=manylinux2014-armv7l"./ bazel - ++ bin / tensorflow_lite_support / tools / pip_package / ++ build_pip_package-- dst wheels ${NIGHTLY_FLAG} bazel build - ++ c opt-- config = ++ elinux_aarch64 tensorflow_lite_support / tools / ++ pip_package : build_pip_package EXTRA_PKG_NAME_FLAG = ++ "--plat-name=manylinux2014-aarch64"./ bazel - ++ bin / tensorflow_lite_support / tools / pip_package / ++ build_pip_package-- dst wheels $ { ++ NIGHTLY_FLAG ++} +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh +old mode 100755 +new mode 100644 +index 9e3c0768dad04..fd376bf84ecb6 +--- a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh ++++ b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh +@@ -1,40 +1,53 @@ +-#!/usr/bin/env bash +-# Copyright 2015 The TensorFlow Authors. All Rights Reserved. ++#!/ usr / bin / env bash ++#Copyright 2015 The TensorFlow Authors.All Rights Reserved. + # +-# Licensed under the Apache License, Version 2.0 (the "License"); +-# you may not use this file except in compliance with the License. +-# You may obtain a copy of the License at ++#Licensed under the Apache License, Version 2.0(the "License"); ++#you may not use this file except in compliance with the License. ++#You may obtain a copy of the License at + # +-# http://www.apache.org/licenses/LICENSE-2.0 ++#http: // www.apache.org/licenses/LICENSE-2.0 + # +-# Unless required by applicable law or agreed to in writing, software +-# distributed under the License is distributed on an "AS IS" BASIS, +-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-# See the License for the specific language governing permissions and +-# limitations under the License. +-# ============================================================================== ++#Unless required by applicable law or agreed to in writing, software ++#distributed under the License is distributed on an "AS IS" BASIS, ++#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ++#See the License for the specific language governing permissions and ++#limitations under the License. ++#== == == == == == == == == == == == == == == == == == == == == == == == == == \ ++ == == == == == == == == == == == == == + +-# Select bazel version. +-BAZEL_VERSION="4.2.2" ++#Select bazel version. ++BAZEL_VERSION = "4.2.2" + +-set +e +-local_bazel_ver=$(bazel version 2>&1 | grep -i label | awk '{print $3}') ++ set + ++ e local_bazel_ver = ++ $(bazel version 2 > &1 | grep - i label | awk '{print $3}') + +-if [[ "$local_bazel_ver" == "$BAZEL_VERSION" ]]; then +- exit 0 +-fi ++ if[["$local_bazel_ver" == "$BAZEL_VERSION"]]; ++then exit 0 fi + +-set -e ++ set - ++ e + +-# Install bazel. +-mkdir -p /bazel +-cd /bazel +-if [[ ! -f "bazel-$BAZEL_VERSION-installer-linux-x86_64.sh" ]]; then +- curl -fSsL -O https://github.com/bazelbuild/bazel/releases/download/$BAZEL_VERSION/bazel-$BAZEL_VERSION-installer-linux-x86_64.sh +-fi +-chmod +x /bazel/bazel-*.sh +-/bazel/bazel-$BAZEL_VERSION-installer-linux-x86_64.sh +-rm -f /bazel/bazel-$BAZEL_VERSION-installer-linux-x86_64.sh ++#Install bazel. ++ mkdir - ++ p / bazel cd / ++ bazel if[[!-f "bazel-$BAZEL_VERSION-installer-linux-x86_64.sh"]]; ++then curl - fSsL - ++ O https ++ : // github.com/bazelbuild/bazel/releases/download/$BAZEL_VERSION/bazel-$BAZEL_VERSION-installer-linux-x86_64.sh ++ fi chmod + ++ x / bazel / bazel - ++ *.sh / bazel / bazel - ++ $BAZEL_VERSION - ++ installer - ++ linux - ++ x86_64.sh rm - ++ f / bazel / bazel - ++ $BAZEL_VERSION - ++ installer - ++ linux - ++ x86_64.sh + +-# Enable bazel auto completion. +-echo "source /usr/local/lib/bazel/bin/bazel-complete.bash" >> ~/.bashrc ++#Enable bazel auto completion. ++ echo "source /usr/local/lib/bazel/bin/bazel-complete.bash" >> ++ ~ /.bashrc diff --git a/third_party/tflite_support/src/third_party/fft2d/fft.h b/third_party/tflite_support/src/third_party/fft2d/fft.h index 36d838b7f6280..35dbcc766c169 100644 --- a/third_party/tflite_support/src/third_party/fft2d/fft.h @@ -43838,6 +43042,26 @@ #ifdef __cplusplus } +diff --git a/third_party/tflite_support/src/third_party/pybind11_protobuf/com_google_protobuf_build.patch b/third_party/tflite_support/src/third_party/pybind11_protobuf/com_google_protobuf_build.patch +index 01ecf027b5ac1..605337839c0fe 100644 +--- a/third_party/tflite_support/src/third_party/pybind11_protobuf/com_google_protobuf_build.patch ++++ b/third_party/tflite_support/src/third_party/pybind11_protobuf/com_google_protobuf_build.patch +@@ -1,9 +1,9 @@ +---- BUILD +-+++ BUILD +-@@ -889,6 +889,8 @@ +- "//conditions:default": [], +- ":use_fast_cpp_protos": ["//external:python_headers"], +- }), ++-- -BUILD++ + BUILD @ @-889, 6 + 889, ++ 8 @@ ++ "//conditions:default" : [], ++ ":use_fast_cpp_protos" ++ : ["//external:python_headers"], ++}), + + + + visibility = ["//visibility:public"], + ) -- -2.34.1.307.g9b7440fafd-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/patches/0009-remove-unbuilt-files-and-change-exec-bit-where-neede.patch b/third_party/tflite_support/patches/0011-remove-unbuilt-files-and-change-exec-bit-where-neede.patch similarity index 80% rename from third_party/tflite_support/patches/0009-remove-unbuilt-files-and-change-exec-bit-where-neede.patch rename to third_party/tflite_support/patches/0011-remove-unbuilt-files-and-change-exec-bit-where-neede.patch index 4ea8bdce..509d392c 100644 --- a/third_party/tflite_support/patches/0009-remove-unbuilt-files-and-change-exec-bit-where-neede.patch +++ b/third_party/tflite_support/patches/0011-remove-unbuilt-files-and-change-exec-bit-where-neede.patch
@@ -1,7 +1,7 @@ -From 515f1ef8496e5c73318aa41f6295bbfbefb6bbae Mon Sep 17 00:00:00 2001 +From d4667e60fd70c1f3dd51d8df9917007b8ffd05c4 Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Thu, 16 Dec 2021 13:56:14 -0800 -Subject: [PATCH 09/11] remove unbuilt files and change exec bit where needed +Date: Mon, 7 Feb 2022 12:14:12 -0800 +Subject: [PATCH 11/12] remove unbuilt files and change exec bit where needed --- .../cc/port/benchmark.h | 21 --- @@ -21,12 +21,16 @@ .../metadata/cc/utils/zip_mem_file.cc | 124 --------------- .../metadata/cc/utils/zip_mem_file.h | 71 --------- .../odml/ios/image/resources/grace_hopper.jpg | Bin + .../task/vision/core/pybinds/image_utils.cc | 68 -------- + .../task/vision/pybinds/image_embedder.cc | 68 -------- .../tools/ci_build/build_all.sh | 0 .../ci_build/builds/build_ios_framework.sh | 0 .../tools/ci_build/builds/pip_smoke_test.sh | 0 .../tools/ci_build/common.sh | 0 .../tools/ci_build/common_win.bat | 0 - 22 files changed, 518 deletions(-) + .../pip_package/rpi/build_arm_pip_package.sh | 0 + .../tools/pip_package/rpi/install_bazel.sh | 0 + 26 files changed, 654 deletions(-) delete mode 100644 third_party/tflite_support/src/tensorflow_lite_support/cc/port/benchmark.h delete mode 100644 third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/status_matchers.h delete mode 100644 third_party/tflite_support/src/tensorflow_lite_support/cc/port/gmock.h @@ -44,11 +48,15 @@ delete mode 100644 third_party/tflite_support/src/tensorflow_lite_support/metadata/cc/utils/zip_mem_file.cc delete mode 100644 third_party/tflite_support/src/tensorflow_lite_support/metadata/cc/utils/zip_mem_file.h mode change 100755 => 100644 third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/resources/grace_hopper.jpg + delete mode 100644 third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/pybinds/image_utils.cc + delete mode 100644 third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/pybinds/image_embedder.cc mode change 100644 => 100755 third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/build_all.sh mode change 100644 => 100755 third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/builds/build_ios_framework.sh mode change 100644 => 100755 third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/builds/pip_smoke_test.sh mode change 100644 => 100755 third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common.sh mode change 100644 => 100755 third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common_win.bat + mode change 100644 => 100755 third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh + mode change 100644 => 100755 third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/port/benchmark.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/port/benchmark.h deleted file mode 100644 @@ -646,6 +654,154 @@ diff --git a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/resources/grace_hopper.jpg b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/resources/grace_hopper.jpg old mode 100755 new mode 100644 +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/pybinds/image_utils.cc b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/pybinds/image_utils.cc +deleted file mode 100644 +index 8834d0e36816d..0000000000000 +--- a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/pybinds/image_utils.cc ++++ /dev/null +@@ -1,68 +0,0 @@ +-/* Copyright 2020 The TensorFlow Authors. All Rights Reserved. +- +-Licensed under the Apache License, Version 2.0 (the "License"); +-you may not use this file except in compliance with the License. +-You may obtain a copy of the License at +- +- http://www.apache.org/licenses/LICENSE-2.0 +- +-Unless required by applicable law or agreed to in writing, software +-distributed under the License is distributed on an "AS IS" BASIS, +-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-See the License for the specific language governing permissions and +-limitations under the License. +-==============================================================================*/ +-#include "tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.h" +- +-#include "pybind11/pybind11.h" +-#include "pybind11_abseil/status_casters.h" // from @pybind11_abseil +- +-namespace tflite { +-namespace task { +-namespace vision { +- +-namespace { +-namespace py = ::pybind11; +- +-} // namespace +- +-PYBIND11_MODULE(image_utils, m) { +- // python wrapper for ImageData class which shouldn't be directly used by +- // the users. +- pybind11::google::ImportStatusModule(); +- +- py::class_<ImageData>(m, "ImageData", py::buffer_protocol()) +- .def(py::init([](py::buffer buffer) { +- py::buffer_info info = buffer.request(); +- +- if (info.ndim != 2 && info.ndim != 3) { +- throw py::value_error("Incompatible buffer dimension!"); +- } +- +- int height = info.shape[0]; +- int width = info.shape[1]; +- int channels = info.ndim == 3 ? info.shape[2] : 1; +- +- return ImageData{static_cast<uint8 *>(info.ptr), width, height, +- channels}; +- })) +- .def_readonly("width", &ImageData::width) +- .def_readonly("height", &ImageData::height) +- .def_readonly("channels", &ImageData::channels) +- .def_buffer([](ImageData &data) -> py::buffer_info { +- return py::buffer_info( +- data.pixel_data, sizeof(uint8), +- py::format_descriptor<uint8>::format(), 3, +- {data.height, data.width, data.channels}, +- {sizeof(uint8) * size_t(data.width) * size_t(data.channels), +- sizeof(uint8) * size_t(data.channels), sizeof(uint8)}); +- }); +- +- m.def("DecodeImageFromFile", &DecodeImageFromFile); +- m.def("EncodeImageToPngFile", &EncodeImageToPngFile); +- m.def("ImageDataFree", &ImageDataFree); +-} +- +-} // namespace vision +-} // namespace task +-} // namespace tflite +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/pybinds/image_embedder.cc b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/pybinds/image_embedder.cc +deleted file mode 100644 +index 073a688780ca0..0000000000000 +--- a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/pybinds/image_embedder.cc ++++ /dev/null +@@ -1,68 +0,0 @@ +-/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. +- +-Licensed under the Apache License, Version 2.0 (the "License"); +-you may not use this file except in compliance with the License. +-You may obtain a copy of the License at +- +- http://www.apache.org/licenses/LICENSE-2.0 +- +-Unless required by applicable law or agreed to in writing, software +-distributed under the License is distributed on an "AS IS" BASIS, +-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +-See the License for the specific language governing permissions and +-limitations under the License. +-==============================================================================*/ +- +-#include "tensorflow_lite_support/cc/task/vision/image_embedder.h" +- +-#include "pybind11/pybind11.h" +-#include "pybind11_abseil/status_casters.h" // from @pybind11_abseil +-#include "pybind11_protobuf/native_proto_caster.h" // from @pybind11_protobuf +-#include "tensorflow_lite_support/cc/port/statusor.h" +-#include "tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.h" +- +-namespace tflite { +-namespace task { +-namespace vision { +- +-namespace { +-namespace py = ::pybind11; +-} // namespace +- +-PYBIND11_MODULE(_pywrap_image_embedder, m) { +- // python wrapper for C++ ImageEmbeder class which shouldn't be directly used +- // by the users. +- pybind11::google::ImportStatusModule(); +- pybind11_protobuf::ImportNativeProtoCasters(); +- +- py::class_<ImageEmbedder>(m, "ImageEmbedder") +- .def_static( +- "create_from_options", +- [](const ImageEmbedderOptions& options) { +- return ImageEmbedder::CreateFromOptions(options); +- }) +- .def("embed", +- [](ImageEmbedder& self, const ImageData& image_data) +- -> tflite::support::StatusOr<EmbeddingResult> { +- ASSIGN_OR_RETURN(std::unique_ptr<FrameBuffer> frame_buffer, +- CreateFrameBufferFromImageData(image_data)); +- return self.Embed(*frame_buffer); +- }) +- .def("embed", +- [](ImageEmbedder& self, const ImageData& image_data, +- const BoundingBox& bounding_box) +- -> tflite::support::StatusOr<EmbeddingResult> { +- ASSIGN_OR_RETURN(std::unique_ptr<FrameBuffer> frame_buffer, +- CreateFrameBufferFromImageData(image_data)); +- return self.Embed(*frame_buffer, bounding_box); +- }) +- .def("get_embedding_by_index", &ImageEmbedder::GetEmbeddingByIndex) +- .def("get_number_of_output_layers", +- &ImageEmbedder::GetNumberOfOutputLayers) +- .def("get_embedding_dimension", &ImageEmbedder::GetEmbeddingDimension) +- .def_static("cosine_similarity", &ImageEmbedder::CosineSimilarity); +-} +- +-} // namespace vision +-} // namespace task +-} // namespace tflite diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/build_all.sh b/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/build_all.sh old mode 100644 new mode 100755 @@ -661,6 +817,12 @@ diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common_win.bat b/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common_win.bat old mode 100644 new mode 100755 +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh +old mode 100644 +new mode 100755 +diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh +old mode 100644 +new mode 100755 -- -2.34.1.307.g9b7440fafd-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/patches/0012-rm-stdio-static-init.patch b/third_party/tflite_support/patches/0012-rm-stdio-static-init.patch index 4562b6d..b3a54eb0 100644 --- a/third_party/tflite_support/patches/0012-rm-stdio-static-init.patch +++ b/third_party/tflite_support/patches/0012-rm-stdio-static-init.patch
@@ -1,7 +1,7 @@ -From f3ab1569fa4dfd69f74d1bb9c6d1c2c26e9215ce Mon Sep 17 00:00:00 2001 +From 4ba6e88fc7aced0d8e7dd4ea033902025788439e Mon Sep 17 00:00:00 2001 From: Robert Ogden <robertogden@chromium.org> -Date: Fri, 7 Jan 2022 09:30:06 -0800 -Subject: [PATCH] rm stdio static init +Date: Mon, 7 Feb 2022 12:15:03 -0800 +Subject: [PATCH 12/12] rm stdio static init --- .../cc/task/core/tflite_engine.cc | 15 --------------- @@ -34,5 +34,5 @@ using ::tflite::proto::ComputeSettings; using ::tflite::support::CreateStatusWithPayload; -- -2.34.1.575.g55b058a8bb-goog +2.35.0.263.gb82422642f-goog
diff --git a/third_party/tflite_support/src/.bazelversion b/third_party/tflite_support/src/.bazelversion index 47b6be3f..078bf8b7 100644 --- a/third_party/tflite_support/src/.bazelversion +++ b/third_party/tflite_support/src/.bazelversion
@@ -1 +1 @@ -3.7.2 \ No newline at end of file +4.2.2 \ No newline at end of file
diff --git a/third_party/tflite_support/src/WORKSPACE b/third_party/tflite_support/src/WORKSPACE index c7834d3..f35cb3ee 100644 --- a/third_party/tflite_support/src/WORKSPACE +++ b/third_party/tflite_support/src/WORKSPACE
@@ -42,6 +42,12 @@ ) http_file( + name = "mobilebert_embedding_with_metadata", + sha256 = "fa47142dcc6f446168bc672f2df9605b6da5d0c0d6264e9be62870282365b95c", + urls = ["https://storage.googleapis.com/download.tensorflow.org/models/tflite_support/bert_embedder/mobilebert_embedding_with_metadata.tflite"], +) + +http_file( name = "bert_nl_classifier", sha256 = "1e5a550c09bff0a13e61858bcfac7654d7fcc6d42106b4f15e11117695069600", urls = ["https://storage.googleapis.com/download.tensorflow.org/models/tflite_support/bert_nl_classifier/bert_nl_classifier.tflite"], @@ -75,28 +81,24 @@ # https://github.com/bazelbuild/rules_apple/releases http_archive( name = "build_bazel_rules_apple", - sha256 = "ee9e6073aeb5a65c100cb9c44b0017c937706a4ae03176e14a7e78620a198079", - strip_prefix = "rules_apple-5131f3d46794bf227d296c82f30c2499c9de3c5b", + sha256 = "0052d452af7742c8f3a4e0929763388a66403de363775db7e90adecb2ba4944b", urls = [ - "https://storage.googleapis.com/mirror.tensorflow.org/github.com/bazelbuild/rules_apple/archive/5131f3d46794bf227d296c82f30c2499c9de3c5b.tar.gz", - "https://github.com/bazelbuild/rules_apple/archive/5131f3d46794bf227d296c82f30c2499c9de3c5b.tar.gz", + "https://github.com/bazelbuild/rules_apple/releases/download/0.31.3/rules_apple.0.31.3.tar.gz", ], ) # https://github.com/bazelbuild/rules_swift/releases http_archive( name = "build_bazel_rules_swift", - sha256 = "d0833bc6dad817a367936a5f902a0c11318160b5e80a20ece35fb85a5675c886", - strip_prefix = "rules_swift-3eeeb53cebda55b349d64c9fc144e18c5f7c0eb8", + sha256 = "8407fa0fd04a7ce1d6bb95e90b216404466f809eda459c23cb57b5fa1ef9d639", urls = [ - "https://storage.googleapis.com/mirror.tensorflow.org/github.com/bazelbuild/rules_swift/archive/3eeeb53cebda55b349d64c9fc144e18c5f7c0eb8.tar.gz", - "https://github.com/bazelbuild/rules_swift/archive/3eeeb53cebda55b349d64c9fc144e18c5f7c0eb8.tar.gz", + "https://github.com/bazelbuild/rules_swift/releases/download/0.21.0/rules_swift.0.21.0.tar.gz", ], ) -# TF on 2021-11-09. -TENSORFLOW_COMMIT = "6a144e7763914d3f6141a7cdc9cb116cc23425f9" -TENSORFLOW_SHA256 = "cec9a514c09d2b171ad447f3413151b25a6c3d88d048148cced1e85db81f3617" +# TF on 2022-01-28. +TENSORFLOW_COMMIT = "f2c2144d767a64236261fb4e4dd45947bd5f5815" +TENSORFLOW_SHA256 = "32ba2f6ea07572fd05cdae7520fe1bc38409f1a21bb4524076df27f1e23d09c1" http_archive( name = "org_tensorflow", sha256 = TENSORFLOW_SHA256, @@ -123,12 +125,36 @@ third_party_http_archive( name = "pybind11", urls = [ - "https://storage.googleapis.com/mirror.tensorflow.org/github.com/pybind/pybind11/archive/v2.6.0.tar.gz", - "https://github.com/pybind/pybind11/archive/v2.6.0.tar.gz", + "https://storage.googleapis.com/mirror.tensorflow.org/github.com/pybind/pybind11/archive/v2.7.1.tar.gz", + "https://github.com/pybind/pybind11/archive/v2.7.1.tar.gz", ], - sha256 = "90b705137b69ee3b5fc655eaca66d0dc9862ea1759226f7ccd3098425ae69571", - strip_prefix = "pybind11-2.6.0", - build_file = "//third_party:pybind11.BUILD", + sha256 = "616d1c42e4cf14fa27b2a4ff759d7d7b33006fdc5ad8fd603bb2c22622f27020", + strip_prefix = "pybind11-2.7.1", + build_file = "@pybind11_bazel//:pybind11.BUILD", +) + +# TODO(b/211393391): Updates the commit number once the new change is ready. +PP_COMMIT = "30f02dd9ccd2fc7046c36ed913ed510fd1aa7301" +PP_SHA256 = "178bcd587956b0f449fff2f46e663dc10baa6d4951a0a7f48cddfeef57d593a8" +http_archive( + name = "pybind11_protobuf", + sha256 = PP_SHA256, + strip_prefix = "pybind11_protobuf-{commit}".format(commit = PP_COMMIT), + urls = [ + "https://github.com/pybind/pybind11_protobuf/archive/{commit}.tar.gz".format(commit = PP_COMMIT), + ], +) + +http_archive( + name = "com_google_protobuf", + sha256 = "bb1ddd8172b745cbdc75f06841bd9e7c9de0b3956397723d883423abfab8e176", + strip_prefix = "protobuf-3.18.0", + # Patched to give visibility into private targets to pybind11_protobuf + patches = ["//third_party/pybind11_protobuf:com_google_protobuf_build.patch"], + urls = [ + "https://github.com/protocolbuffers/protobuf/archive/v3.18.0.zip", + ], + repo_mapping = {"@six": "@six_archive"}, ) http_archive( @@ -383,8 +409,8 @@ http_archive( name = "robolectric", - urls = ["https://github.com/robolectric/robolectric-bazel/archive/4.4.tar.gz"], - strip_prefix = "robolectric-bazel-4.4", + urls = ["https://github.com/robolectric/robolectric-bazel/archive/4.7.3.tar.gz"], + strip_prefix = "robolectric-bazel-4.7.3", ) load("@robolectric//bazel:robolectric.bzl", "robolectric_repositories") robolectric_repositories() @@ -393,13 +419,13 @@ flatbuffers() -RULES_JVM_EXTERNAL_TAG = "3.2" +RULES_JVM_EXTERNAL_TAG = "4.2" http_archive( name = "rules_jvm_external", strip_prefix = "rules_jvm_external-%s" % RULES_JVM_EXTERNAL_TAG, - sha256 = "82262ff4223c5fda6fb7ff8bd63db8131b51b413d26eb49e3131037e79e324af", - url = "https://github.com/bazelbuild/rules_jvm_external/archive/%s.zip" % RULES_JVM_EXTERNAL_TAG, + sha256 = "cd1a77b7b02e8e008439ca76fd34f5b07aecb8c752961f9640dea15e9e5ba1ca", + url = "https://github.com/bazelbuild/rules_jvm_external/archive/refs/tags/%s.zip" % RULES_JVM_EXTERNAL_TAG, ) load("@rules_jvm_external//:defs.bzl", "maven_install") @@ -464,7 +490,7 @@ "org.mockito:mockito-android:jar:3.0.0", "org.mockito:mockito-core:jar:3.0.0", "org.mockito:mockito-inline:jar:3.0.0", - "org.robolectric:robolectric:jar:4.4", + "org.robolectric:robolectric:jar:4.7.3", "junit:junit:jar:4.13", ], repositories = [
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/core/utils/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/c/task/core/utils/BUILD new file mode 100644 index 0000000..7c8d7f1 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/core/utils/BUILD
@@ -0,0 +1,13 @@ +package( + default_visibility = ["//tensorflow_lite_support:internal"], + licenses = ["notice"], # Apache 2.0 +) + +cc_library( + name = "base_options_utils", + srcs = ["base_options_utils.cc"], + hdrs = ["base_options_utils.h"], + deps = [ + "//tensorflow_lite_support/c/task/core:base_options", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/core/utils/base_options_utils.cc b/third_party/tflite_support/src/tensorflow_lite_support/c/task/core/utils/base_options_utils.cc new file mode 100644 index 0000000..588e487 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/core/utils/base_options_utils.cc
@@ -0,0 +1,30 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow_lite_support/c/task/core/utils/base_options_utils.h" + +namespace tflite { +namespace task { +namespace core { + +TfLiteBaseOptions CreateDefaultBaseOptions() { + TfLiteBaseOptions base_options = {{0}}; + base_options.compute_settings.cpu_settings.num_threads = -1; + return base_options; +} + +} // namespace core +} // namespace task +} // namespace tflite
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/core/utils/base_options_utils.h b/third_party/tflite_support/src/tensorflow_lite_support/c/task/core/utils/base_options_utils.h new file mode 100644 index 0000000..980ff073 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/core/utils/base_options_utils.h
@@ -0,0 +1,30 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_SUPPORT_C_TASK_CORE_UTILS_BASE_OPTIONS_UTILS_H_ +#define TENSORFLOW_LITE_SUPPORT_C_TASK_CORE_UTILS_BASE_OPTIONS_UTILS_H_ + +#include "tensorflow_lite_support/c/task/core/base_options.h" + +// Utils for Creating TfLiteBaseOptions +namespace tflite { +namespace task { +namespace core { + +TfLiteBaseOptions CreateDefaultBaseOptions(); + +} // namespace core +} // namespace task +} // namespace tflite +#endif // TENSORFLOW_LITE_SUPPORT_C_TASK_CORE_UTILS_BASE_OPTIONS_UTILS_H_
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/BUILD index 2d0cef68..e6e5e685 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/BUILD
@@ -5,6 +5,7 @@ cc_library( name = "category", + srcs = ["category.cc"], hdrs = ["category.h"], ) @@ -40,3 +41,8 @@ ":category", ], ) + +cc_library( + name = "segmentation_result", + hdrs = ["segmentation_result.h"], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/category.cc b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/category.cc new file mode 100644 index 0000000..4ecba762 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/category.cc
@@ -0,0 +1,34 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow_lite_support/c/task/processor/category.h" + +#include <cstdlib> +#include <memory> + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void TfLiteCategoryDelete(TfLiteCategory* category) { + // `strdup` obtains memory using `malloc` and the memory needs to be + // released using `free`. + free(category->display_name); + free(category->label); +} + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/category.h b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/category.h index 5c049ec..3ff0d22 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/category.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/category.h
@@ -42,6 +42,9 @@ char* label; } TfLiteCategory; +// Frees up the TfLiteCategory Structure. +void TfLiteCategoryDelete(TfLiteCategory* category); + #ifdef __cplusplus } // extern "C" #endif // __cplusplus
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/classification_result.cc b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/classification_result.cc index c277df0..0c18c58 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/classification_result.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/classification_result.cc
@@ -28,10 +28,7 @@ TfLiteClassifications classifications = classification_result->classifications[head]; for (int rank = 0; rank < classifications.size; ++rank) { - // `strdup` obtains memory using `malloc` and the memory needs to be - // released using `free`. - free(classifications.categories[rank].display_name); - free(classifications.categories[rank].label); + TfLiteCategoryDelete(&(classifications.categories[rank])); } delete[] classifications.categories;
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/detection_result.cc b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/detection_result.cc new file mode 100644 index 0000000..62057af --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/detection_result.cc
@@ -0,0 +1,41 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow_lite_support/c/task/processor/detection_result.h" + +#include <cstdlib> +#include <memory> + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +void TfLiteDetectionResultDelete(TfLiteDetectionResult* detection_result) { + for (int i = 0; i < detection_result->size; ++i) { + TfLiteDetection detections = detection_result->detections[i]; + for (int j = 0; j < detections.size; ++j) { + TfLiteCategoryDelete(&(detections.categories[j])); + } + + delete[] detections.categories; + } + + delete[] detection_result->detections; + delete detection_result; +} + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/segmentation_result.h b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/segmentation_result.h new file mode 100644 index 0000000..6cc211f6 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/segmentation_result.h
@@ -0,0 +1,110 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_SUPPORT_C_TASK_PROCESSOR_SEGMENTATION_RESULT_H_ +#define TENSORFLOW_LITE_SUPPORT_C_TASK_PROCESSOR_SEGMENTATION_RESULT_H_ + +#include <stdint.h> + +// Defines C structure for Image Segmentation Results and associated helper +// methods. + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +// Holds a label associated with an RGB color, for display purposes. +typedef struct TfLiteColoredLabel { + // The RGB color components for the label, in the [0, 255] range. + unsigned int r; + unsigned int g; + unsigned int b; + + // The class name, as provided in the label map packed in the TFLite Model + // Metadata. + char* label; + + // The display name, as provided in the label map (if available) packed in + // the TFLite Model Metadata. See `display_names_locale` field in + // ImageSegmenterOptions. + char* display_name; + +} TfLiteColoredLabel; + +// Holds a resulting segmentation mask and associated metadata. +typedef struct TfLiteSegmentation { + // The width of the mask. This is an intrinsic parameter of the model being + // used, and does not depend on the input image dimensions. + unsigned int width; + + // The height of the mask. This is an intrinsic parameter of the model being + // used, and does not depend on the input image dimensions. + unsigned int height; + + // IMPORTANT: A TfLiteSegmentation can either have `confidence_masks` + // or `category_mask` based on the output type selected in + // `TfLiteSegmentationOptions`i.e, they are mutually exclusive. + // Whichever field amongst the two is not applicable based on the selected + // output type will be null. + + // IMPORTANT: segmentation masks are not direcly suited for display, in + // particular: + // * they are relative to the unrotated input frame, i.e. *not* taking into + // account the `Orientation` flag of the input FrameBuffer, + // * their dimensions are intrinsic to the model, i.e. *not* dependent on the + // input FrameBuffer dimensions. + + // One confidence masks of size `width` x `height` for each of the supported + // classes. The value of each pixel in these masks represents the confidence + // score for this particular class. + float** confidence_masks; + + // Flattened 2D-array of size `width` x `height`, + // in row major order. The value of each pixel in this mask represents the + // class to which the pixel belongs. + uint8_t* category_mask; + + // The list of colored labels for all the supported categories (classes). + // Depending on which is present, this list is in 1:1 correspondence with: + // * `category_mask` pixel values, i.e. a pixel with value `i` is + // associated with `colored_labels[i]`, + // * `confidence_masks` indices, i.e. `confidence_masks[i]` is associated with + // `colored_labels[i]`. + TfLiteColoredLabel* colored_labels; + +} TfLiteSegmentation; + +// Holds Image Segmentation Results. +// Contains one set of results per detected object. +typedef struct TfLiteSegmentationResult { + // Number of segmentations be used to traverse the array of segmentations. + int size; + + // Array of seegmentations returned after inference by model. + // Note that at the time, this array is expected to have a single + // `TfLiteSegmentation`; the field is made an array for later extension to + // e.g. instance segmentation models, which may return one segmentation per + // object. + TfLiteSegmentation* segmentations; +} TfLiteSegmentationResult; + +// Frees up the TfLiteSegmentationResult Structure. +void TfLiteSegmentationResultDelete( + TfLiteSegmentationResult* segmentation_result); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // TENSORFLOW_LITE_SUPPORT_C_TASK_VISION_SEGMENTATION_RESULT_H_
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/utils/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/utils/BUILD new file mode 100644 index 0000000..c48cd7e0 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/utils/BUILD
@@ -0,0 +1,13 @@ +package( + default_visibility = ["//tensorflow_lite_support:internal"], + licenses = ["notice"], # Apache 2.0 +) + +cc_library( + name = "classification_options_utils", + srcs = ["classification_options_utils.cc"], + hdrs = ["classification_options_utils.h"], + deps = [ + "//tensorflow_lite_support/c/task/processor:classification_options", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/utils/classification_options_utils.cc b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/utils/classification_options_utils.cc new file mode 100644 index 0000000..ea35b79c --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/utils/classification_options_utils.cc
@@ -0,0 +1,33 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow_lite_support/c/task/processor/utils/classification_options_utils.h" + +#include <float.h> + +namespace tflite { +namespace task { +namespace processor { + +TfLiteClassificationOptions CreateDefaultClassificationOptions() { + TfLiteClassificationOptions classification_options = {{0}}; + classification_options.max_results = -1; + classification_options.score_threshold = -FLT_MAX; + return classification_options; +} + +} // namespace processor +} // namespace task +} // namespace tflite
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/utils/classification_options_utils.h b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/utils/classification_options_utils.h new file mode 100644 index 0000000..666573f3 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/processor/utils/classification_options_utils.h
@@ -0,0 +1,31 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_SUPPORT_C_TASK_PROCESSOR_UTILS_CLASSIFICATION_OPTIONS_UTILS_H_ +#define TENSORFLOW_LITE_SUPPORT_C_TASK_PROCESSOR_UTILS_CLASSIFICATION_OPTIONS_UTILS_H_ + +#include "tensorflow_lite_support/c/task/processor/classification_options.h" + +// Utils for Creating TfLiteClassificationOptions + +namespace tflite { +namespace task { +namespace processor { + +TfLiteClassificationOptions CreateDefaultClassificationOptions(); + +} // namespace processor +} // namespace task +} // namespace tflite +#endif // TENSORFLOW_LITE_SUPPORT_C_TASK_PROCESSOR_UTILS_CLASSIFICATION_OPTIONS_UTILS_H_
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/BUILD index 5bd132a5..8e3538f 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/BUILD
@@ -22,9 +22,11 @@ "//tensorflow_lite_support/c:common", "//tensorflow_lite_support/c:common_utils", "//tensorflow_lite_support/c/task/core:base_options", + "//tensorflow_lite_support/c/task/core/utils:base_options_utils", "//tensorflow_lite_support/c/task/processor:bounding_box", "//tensorflow_lite_support/c/task/processor:classification_options", "//tensorflow_lite_support/c/task/processor:classification_result", + "//tensorflow_lite_support/c/task/processor/utils:classification_options_utils", "//tensorflow_lite_support/c/task/vision/core:frame_buffer", "//tensorflow_lite_support/c/task/vision/utils:frame_buffer_cpp_c_utils", "//tensorflow_lite_support/cc/task/vision/proto:classifications_proto_inc", @@ -34,6 +36,9 @@ cc_library_with_tflite( name = "object_detector", + srcs = [ + "object_detector.cc", + ], hdrs = [ "object_detector.h", ], @@ -42,9 +47,32 @@ ], deps = [ "//tensorflow_lite_support/c:common", + "//tensorflow_lite_support/c:common_utils", "//tensorflow_lite_support/c/task/core:base_options", + "//tensorflow_lite_support/c/task/core/utils:base_options_utils", + "//tensorflow_lite_support/c/task/processor:bounding_box", "//tensorflow_lite_support/c/task/processor:classification_options", "//tensorflow_lite_support/c/task/processor:detection_result", + "//tensorflow_lite_support/c/task/processor/utils:classification_options_utils", + "//tensorflow_lite_support/c/task/vision/core:frame_buffer", + "//tensorflow_lite_support/c/task/vision/utils:frame_buffer_cpp_c_utils", + "//tensorflow_lite_support/cc/task/vision/proto:detections_proto_inc", + "//tensorflow_lite_support/cc/task/vision/proto:object_detector_options_proto_inc", + ], +) + +cc_library_with_tflite( + name = "image_segmenter", + hdrs = [ + "image_segmenter.h", + ], + tflite_deps = [ + "//tensorflow_lite_support/cc/task/vision:image_segmenter", + ], + deps = [ + "//tensorflow_lite_support/c:common", + "//tensorflow_lite_support/c/task/core:base_options", + "//tensorflow_lite_support/c/task/processor:segmentation_result", "//tensorflow_lite_support/c/task/vision/core:frame_buffer", ], )
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_classifier.cc b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_classifier.cc index 8981e66..b3517ad 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_classifier.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_classifier.cc
@@ -18,6 +18,8 @@ #include <memory> #include "tensorflow_lite_support/c/common_utils.h" +#include "tensorflow_lite_support/c/task/core/utils/base_options_utils.h" +#include "tensorflow_lite_support/c/task/processor/utils/classification_options_utils.h" #include "tensorflow_lite_support/c/task/vision/utils/frame_buffer_cpp_c_utils.h" #include "tensorflow_lite_support/cc/task/vision/image_classifier.h" #include "tensorflow_lite_support/cc/task/vision/proto/classifications_proto_inc.h" @@ -100,10 +102,10 @@ TfLiteImageClassifierOptions TfLiteImageClassifierOptionsCreate() { // Use brace-enclosed initializer list will break the Kokoro test. - TfLiteImageClassifierOptions options = {{{0}}}; - options.classification_options.max_results = -1; - options.classification_options.score_threshold = 0.0; - options.base_options.compute_settings.cpu_settings.num_threads = -1; + TfLiteImageClassifierOptions options; + options.classification_options = + tflite::task::processor::CreateDefaultClassificationOptions(); + options.base_options = tflite::task::core::CreateDefaultBaseOptions(); return options; } @@ -206,8 +208,7 @@ // fnc_sample(cpp_frame_buffer_status); StatusOr<ClassificationResultCpp> cpp_classification_result_status = - classifier->impl->Classify(*std::move(cpp_frame_buffer_status.value()), - cc_roi); + classifier->impl->Classify(*(cpp_frame_buffer_status.value()), cc_roi); if (!cpp_classification_result_status.ok()) { tflite::support::CreateTfLiteSupportErrorWithStatus(
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_segmenter.h b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_segmenter.h new file mode 100644 index 0000000..23b6b6e --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/image_segmenter.h
@@ -0,0 +1,214 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#ifndef TENSORFLOW_LITE_SUPPORT_C_TASK_VISION_IMAGE_SEGMENTER_H_ +#define TENSORFLOW_LITE_SUPPORT_C_TASK_VISION_IMAGE_SEGMENTER_H_ + +#include <stdint.h> + +#include "tensorflow_lite_support/c/common.h" +#include "tensorflow_lite_support/c/task/core/base_options.h" +#include "tensorflow_lite_support/c/task/processor/segmentation_result.h" +#include "tensorflow_lite_support/c/task/vision/core/frame_buffer.h" + +// -------------------------------------------------------------------------- +/// C API for ImageSegmenter. +/// +/// The API leans towards simplicity and uniformity instead of convenience, as +/// most usage will be by language-specific wrappers. It provides largely the +/// same set of functionality as that of the C++ TensorFlow Lite +/// `ImageSegmenter` API, but is useful for shared libraries where having +/// a stable ABI boundary is important. +/// +/// Usage: +/// <pre><code> +/// // Create the model +/// Using the options initialized with default values returned by +/// TfLiteImageSegmenterOptionsCreate() makes sure that there will be no +/// undefined behaviour due to garbage values in unitialized members. +/// TfLiteImageSegmenterOptions options = TfLiteImageSegmenterOptionsCreate(); +/// +/// Set the model file path in options +/// options.base_options.model_file.file_path = "/path/to/model.tflite"; +/// +/// If need be, set values for any options to customize behaviour. +/// options.base_options.compute_settings.cpu_settings.num_threads = 3 +/// +/// Create TfLiteImageSegmenter using the options: +/// If error information is not needed in case of failure: +/// TfLiteImageSegmenter* image_segmenter = +/// TfLiteImageSegmenterFromOptions(&options, NULL); +/// +/// If error information is needed in case of failure: +/// TfLiteSupportError* create_error = NULL; +/// TfLiteImageSegmenter* image_segmenter = +/// TTfLiteImageSegmenterFromOptions(&options, &create_error); +/// +/// if (!image_segmenter) { +/// Handle failure. +/// Do something with `create_error`, if requested as illustrated above. +/// } +/// +/// Dispose of the create_error object. +/// TfLiteSupportErrorDelete(create_error); +/// +/// Classify an image +/// TfLiteFrameBuffer frame_buffer = { Initialize with image data } +/// +/// If error information is not needed in case of failure: +/// TfLiteSegmentationResult* segmentation_result = +/// TfLiteImageSegmenterSegment(image_segmenter, &frame_buffer, NULL); +/// +/// If error information is needed in case of failure: +/// TfLiteSupportError* segment_error = NULL; +/// TfLiteSegmentationResult* segmentation_result = +/// TfLiteImageSegmenterSegment(image_segmenter, &frame_buffer, +/// &segment_error); +/// +/// if (!segmentation_result) { +/// Handle failure. +/// Do something with `segment_error`, if requested as illustrated above. +/// } +/// +/// Dispose of the segment_error object. +/// TfLiteSupportErrorDelete(segment_error); +/// +/// Dispose of the API object. +/// TfLiteImageClassifierDelete(image_segmenter); + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +typedef struct TfLiteImageSegmenter TfLiteImageSegmenter; + +// Specifies the type of output segmentation mask to be returned +// as a result of the image segmentation operation. +// This allows specifying the type of post-processing to +// perform on the raw model results (see TfLiteSegmentationResult for more). +enum TfLiteImageSegmenterOutputType { + kUnspecified, + // Gives a single output mask where each pixel represents the class which + // the pixel in the original image was predicted to belong to. + kCategoryMask, + + // Gives a list of output masks where, for each mask, each pixel represents + // the prediction confidence, usually in the [0, 1] range. + kConfidenceMask +}; + +// Holds options for configuring the creation of TfLiteImageSegmenter. +typedef struct TfLiteImageSegmenterOptions { + TfLiteBaseOptions base_options; + + // Specifies the type of output segmentation mask to be returned + // as a result of the image segmentation operation. (See + // TfLiteImageSegmenterOutputType for more). + TfLiteImageSegmenterOutputType output_type; + + // The locale to use for display names specified through the TFLite Model + // Metadata, if any. Defaults to English. + char* display_names_locale; +} TfLiteImageSegmenterOptions; + +// Creates and returns TfLiteImageSegmenterOptions initialized with default +// values. Default values are as follows: +// 1. .base_options.compute_settings.tflite_settings.cpu_settings.num_threads = +// -1, which makes the TFLite runtime choose the value. +// 2. .output_type = kCategoryMask +// 3. display_names_locale is NULL. +TfLiteImageSegmenterOptions TfLiteImageSegmenterOptionsCreate(); + +// Creates TfLiteImageSegmenter from options. +// .base_options.model_file.file_path in TfLiteImageSegmenterOptions should be +// set to the path of the tflite model you wish to create the +// TfLiteImageSegmenter with. +// Create TfLiteImageSegmenterOptions using +// TfLiteImageSegmenterOptionsCreate(). If need be, you can change the default +// values of options for customizing segmentation, If options are not created +// in the aforementioned way, you have to make sure that all members are +// initialized to respective default values and all pointer members are zero +// initialized to avoid any undefined behaviour. +// +// Returns the created image segmenter in case of success. +// Returns nullptr on failure which happens commonly due to one of the following +// issues: +// 1. file doesn't exist or is not a well formatted. +// 2. options is nullptr. +// +// The caller can check if an error was encountered by testing if the returned +// value of the function is null. If the caller doesn't want the reason for +// failure, they can simply pass a NULL for the address of the error pointer as +// shown below: +// +// TfLiteImageSegmenter* segmenter = TfLiteImageSegmenterFromOptions(options, +// NULL); +// +// If the caller wants to be informed of the reason for failure, they must pass +// the address of a pointer of type TfLiteSupportError to the `error` param as +// shown below: +// +// TfLiteSupport *error = NULL: +// TfLiteImageSegmenter* segmenter = TfLiteImageSegmenterFromOptions(options, +// &error); +// +// In case of unsuccessful execution, Once the function returns, the error +// pointer will point to a struct containing the error information. If error +// info is passed back to the caller, it is the responsibility of the caller to +// free the error struct by calling the following method defined in common.h: +// +// TfLiteSupportErrorDelete(error) +// +TfLiteImageSegmenter* TfLiteImageSegmenterFromOptions( + const TfLiteImageSegmenterOptions* options, + TfLiteSupportError** error); + +// Invokes the encapsulated TFLite model and performs image segmentation on +// the frame_buffer. +// Returns a pointer to the created segmentation result in case of success or +// NULL in case of failure. The caller must test the return value to identify +// success or failure. If the caller doesn't want the reason for failure, they +// can simply pass a NULL for the address of the error pointer as shown below: +// +// TfLiteSegmentationResult* segmentation_result = +// TfLiteImageSegmenterSegment(&options, NULL); +// +// If the caller wants to be informed of the reason for failure, they must pass +// the address of a pointer of type TfLiteSupportError to the `error` param as +// shown below: +// +// TfLiteSupport *error = NULL: +// TfLiteSegmentationResult* segmentation_result = +// TfLiteImageSegmenterSegment(&options, &error); +// +// In case of unsuccessful execution, Once the function returns, the error +// pointer will point to a struct containing the error information. If error +// info is passed back to the caller, it is the responsibility of the caller to +// free the error struct by calling the following method defined in common.h: +// +// TfLiteSupportErrorDelete(error) +// +TfLiteSegmentationResult* TfLiteImageSegmenterSegment( + const TfLiteImageSegmenter* segmenter, + const TfLiteFrameBuffer* frame_buffer, + TfLiteSupportError** error); + +// Disposes of the image segmenter. +void TfLiteImageSegmenterDelete(TfLiteImageSegmenter* segmenter); + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus + +#endif // TENSORFLOW_LITE_SUPPORT_C_TASK_VISION_IMAGE_SEGMENTER_H_
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.cc b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.cc new file mode 100644 index 0000000..90af0ac --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.cc
@@ -0,0 +1,212 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow_lite_support/c/task/vision/object_detector.h" + +#include <memory> + +#include "tensorflow_lite_support/c/common_utils.h" +#include "tensorflow_lite_support/c/task/core/utils/base_options_utils.h" +#include "tensorflow_lite_support/c/task/processor/utils/classification_options_utils.h" +#include "tensorflow_lite_support/c/task/vision/utils/frame_buffer_cpp_c_utils.h" +#include "tensorflow_lite_support/cc/task/vision/object_detector.h" +#include "tensorflow_lite_support/cc/task/vision/proto/detections_proto_inc.h" +#include "tensorflow_lite_support/cc/task/vision/proto/object_detector_options_proto_inc.h" + +namespace { +using ::tflite::support::StatusOr; +using DetectionResultCpp = ::tflite::task::vision::DetectionResult; +using DetectionCpp = ::tflite::task::vision::Detection; +using ClassCpp = ::tflite::task::vision::Class; +using BoundingBoxCpp = ::tflite::task::vision::BoundingBox; +using ObjectDetectorCpp = ::tflite::task::vision::ObjectDetector; +using ObjectDetectorOptionsCpp = ::tflite::task::vision::ObjectDetectorOptions; +using FrameBufferCpp = ::tflite::task::vision::FrameBuffer; +using ::tflite::support::TfLiteSupportStatus; + +StatusOr<ObjectDetectorOptionsCpp> CreateObjectDetectorCppOptionsFromCOptions( + const TfLiteObjectDetectorOptions* c_options) { + if (c_options == nullptr) { + return CreateStatusWithPayload( + absl::StatusCode::kInvalidArgument, + absl::StrFormat("Expected non null options."), + TfLiteSupportStatus::kInvalidArgumentError); + } + + ObjectDetectorOptionsCpp cpp_options = {}; + + // More file sources can be added in else ifs + if (c_options->base_options.model_file.file_path) + cpp_options.mutable_base_options()->mutable_model_file()->set_file_name( + c_options->base_options.model_file.file_path); + + // c_options->base_options.compute_settings.num_threads is expected to be + // set to value > 0 or -1. Otherwise invoking + // ImageClassifierCpp::CreateFromOptions() results in a not ok status. + cpp_options.mutable_base_options() + ->mutable_compute_settings() + ->mutable_tflite_settings() + ->mutable_cpu_settings() + ->set_num_threads( + c_options->base_options.compute_settings.cpu_settings.num_threads); + + for (int i = 0; i < c_options->classification_options.label_denylist.length; + i++) + cpp_options.add_class_name_blacklist( + c_options->classification_options.label_denylist.list[i]); + + for (int i = 0; i < c_options->classification_options.label_allowlist.length; + i++) + cpp_options.add_class_name_whitelist( + c_options->classification_options.label_allowlist.list[i]); + + // Check needed since setting a nullptr for this field results in a segfault + // on invocation of ImageClassifierCpp::CreateFromOptions(). + if (c_options->classification_options.display_names_local) { + cpp_options.set_display_names_locale( + c_options->classification_options.display_names_local); + } + + // c_options->classification_options.max_results is expected to be set to -1 + // or any value > 0. Otherwise invoking + // ImageClassifierCpp::CreateFromOptions() results in a not ok status. + cpp_options.set_max_results(c_options->classification_options.max_results); + + cpp_options.set_score_threshold( + c_options->classification_options.score_threshold); + + return cpp_options; +} +} // namespace + +#ifdef __cplusplus +extern "C" { +#endif // __cplusplus + +struct TfLiteObjectDetector { + std::unique_ptr<ObjectDetectorCpp> impl; +}; + +TfLiteObjectDetectorOptions TfLiteObjectDetectorOptionsCreate() { + // Use brace-enclosed initializer list will break the Kokoro test. + TfLiteObjectDetectorOptions options; + options.classification_options = + tflite::task::processor::CreateDefaultClassificationOptions(); + options.base_options = tflite::task::core::CreateDefaultBaseOptions(); + return options; +} + +TfLiteObjectDetector* TfLiteObjectDetectorFromOptions( + const TfLiteObjectDetectorOptions* options, + TfLiteSupportError** error) { + StatusOr<ObjectDetectorOptionsCpp> cpp_option_status = + CreateObjectDetectorCppOptionsFromCOptions(options); + + if (!cpp_option_status.ok()) { + ::tflite::support::CreateTfLiteSupportErrorWithStatus( + cpp_option_status.status(), error); + return nullptr; + } + + StatusOr<std::unique_ptr<ObjectDetectorCpp>> detector_status = + ObjectDetectorCpp::CreateFromOptions(cpp_option_status.value()); + + if (detector_status.ok()) { + return new TfLiteObjectDetector{.impl = std::move(detector_status.value())}; + } else { + ::tflite::support::CreateTfLiteSupportErrorWithStatus( + detector_status.status(), error); + return nullptr; + } +} + +TfLiteDetectionResult* GetDetectionResultCStruct( + const DetectionResultCpp& detection_result_cpp) { + auto c_detections = + new TfLiteDetection[detection_result_cpp.detections_size()]; + + for (int i = 0; i < detection_result_cpp.detections_size(); ++i) { + const DetectionCpp& detection = detection_result_cpp.detections(i); + + c_detections[i].bounding_box.origin_x = detection.bounding_box().origin_x(); + c_detections[i].bounding_box.origin_y = detection.bounding_box().origin_y(); + c_detections[i].bounding_box.width = detection.bounding_box().width(); + c_detections[i].bounding_box.height = detection.bounding_box().height(); + + auto c_categories = new TfLiteCategory[detection.classes_size()]; + c_detections[i].size = detection.classes_size(); + + for (int j = 0; j < detection.classes_size(); ++j) { + const ClassCpp& classification = detection.classes(j); + c_categories[j].index = classification.index(); + c_categories[j].score = classification.score(); + + if (classification.has_class_name()) + c_categories[j].label = strdup(classification.class_name().c_str()); + else + c_categories[j].label = nullptr; + + if (classification.has_display_name()) + c_categories[j].display_name = + strdup(classification.display_name().c_str()); + else + c_categories[j].display_name = nullptr; + } + c_detections[i].categories = c_categories; + } + + auto c_detection_result = new TfLiteDetectionResult; + c_detection_result->detections = c_detections; + c_detection_result->size = detection_result_cpp.detections_size(); + + return c_detection_result; +} + +TfLiteDetectionResult* TfLiteObjectDetectorDetect( + const TfLiteObjectDetector* detector, + const TfLiteFrameBuffer* frame_buffer, + TfLiteSupportError** error) { + if (detector == nullptr) { + tflite::support::CreateTfLiteSupportError( + kInvalidArgumentError, "Expected non null object detector.", error); + return nullptr; + } + + StatusOr<std::unique_ptr<FrameBufferCpp>> cpp_frame_buffer_status = + ::tflite::task::vision::CreateCppFrameBuffer(frame_buffer); + if (!cpp_frame_buffer_status.ok()) { + tflite::support::CreateTfLiteSupportErrorWithStatus( + cpp_frame_buffer_status.status(), error); + return nullptr; + } + + StatusOr<DetectionResultCpp> cpp_detection_result_status = + detector->impl->Detect(*(cpp_frame_buffer_status.value())); + if (!cpp_detection_result_status.ok()) { + tflite::support::CreateTfLiteSupportErrorWithStatus( + cpp_detection_result_status.status(), error); + return nullptr; + } + + return GetDetectionResultCStruct(cpp_detection_result_status.value()); +} + +void TfLiteObjectDetectorDelete(TfLiteObjectDetector* detector) { + delete detector; +} + +#ifdef __cplusplus +} // extern "C" +#endif // __cplusplus
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.h b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.h index 5a2d3e1..b31116e 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/task/vision/object_detector.h
@@ -12,8 +12,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#ifndef TENSORFLOW_LITE_SUPPORT_C_TASK_VISION_IMAGE_CLASSIFIER_H_ -#define TENSORFLOW_LITE_SUPPORT_C_TASK_VISION_IMAGE_CLASSIFIER_H_ +#ifndef TENSORFLOW_LITE_SUPPORT_C_TASK_VISION_OBJECT_DETECTOR_H_ +#define TENSORFLOW_LITE_SUPPORT_C_TASK_VISION_OBJECT_DETECTOR_H_ #include <stdint.h> @@ -197,4 +197,4 @@ } // extern "C" #endif // __cplusplus -#endif // TENSORFLOW_LITE_SUPPORT_C_TASK_VISION_IMAGE_CLASSIFIER_H_ +#endif // TENSORFLOW_LITE_SUPPORT_C_TASK_VISION_OBJECT_DETECTOR_H_
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/test/task/vision/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/c/test/task/vision/BUILD index 788dce4..09f7e08 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/c/test/task/vision/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/test/task/vision/BUILD
@@ -32,3 +32,25 @@ "//tensorflow_lite_support/examples/task/vision/desktop/utils:image_utils", ], ) + +# bazel test tensorflow_lite_support/c/test/task/vision:object_detector_test +cc_test_with_tflite( + name = "object_detector_test", + srcs = ["object_detector_test.cc"], + data = [ + "//tensorflow_lite_support/cc/test/testdata/task/vision:test_images", + "//tensorflow_lite_support/cc/test/testdata/task/vision:test_models", + ], + tflite_deps = [ + "//tensorflow_lite_support/c/task/vision:object_detector", + "@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util", + ], + deps = [ + "//tensorflow_lite_support/c:common", + "//tensorflow_lite_support/c/task/processor:detection_result", + "//tensorflow_lite_support/c/task/vision/core:frame_buffer", + "//tensorflow_lite_support/cc/port:gtest_main", + "//tensorflow_lite_support/cc/test:test_utils", + "//tensorflow_lite_support/examples/task/vision/desktop/utils:image_utils", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/c/test/task/vision/object_detector_test.cc b/third_party/tflite_support/src/tensorflow_lite_support/c/test/task/vision/object_detector_test.cc new file mode 100644 index 0000000..99cd003 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/c/test/task/vision/object_detector_test.cc
@@ -0,0 +1,438 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow_lite_support/c/task/vision/object_detector.h" + +#include <string.h> + +#include "tensorflow/lite/core/shims/cc/shims_test_util.h" +#include "tensorflow_lite_support/c/common.h" +#include "tensorflow_lite_support/c/task/processor/detection_result.h" +#include "tensorflow_lite_support/c/task/vision/core/frame_buffer.h" +#include "tensorflow_lite_support/cc/port/gmock.h" +#include "tensorflow_lite_support/cc/port/gtest.h" +#include "tensorflow_lite_support/cc/port/status_matchers.h" +#include "tensorflow_lite_support/cc/test/test_utils.h" +#include "tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.h" + +namespace tflite { +namespace task { +namespace vision { +namespace { + +using ::testing::HasSubstr; +using ::testing::StrEq; +using ::testing::StrNe; +using ::tflite::support::StatusOr; +using ::tflite::task::JoinPath; + +constexpr char kTestDataDirectory[] = + "/tensorflow_lite_support/cc/test/testdata/task/" + "vision/"; +// Quantized model. +constexpr char kMobileSsdWithMetadata[] = + "coco_ssd_mobilenet_v1_1.0_quant_2018_06_29.tflite"; + +StatusOr<ImageData> LoadImage(const char* image_name) { + return DecodeImageFromFile( + JoinPath("./" /*test src dir*/, kTestDataDirectory, image_name)); +} + +void VerifyDetection(const TfLiteDetection& detection, + TfLiteBoundingBox expected_bounding_box, + float expected_first_score, + const std::string& expected_first_label) { + EXPECT_GE(detection.size, 1); + EXPECT_NE(detection.categories, nullptr); + EXPECT_EQ(detection.bounding_box.origin_x, expected_bounding_box.origin_x); + EXPECT_EQ(detection.bounding_box.origin_y, expected_bounding_box.origin_y); + EXPECT_EQ(detection.bounding_box.height, expected_bounding_box.height); + EXPECT_EQ(detection.bounding_box.width, expected_bounding_box.width); + + EXPECT_THAT(detection.categories[0].label, StrEq(expected_first_label)); + EXPECT_NEAR(detection.categories[0].score, expected_first_score, 0.001); +} + +void VerifyResults(TfLiteDetectionResult* detection_result) { + ASSERT_NE(detection_result, nullptr); + EXPECT_GE(detection_result->size, 1); + EXPECT_NE(detection_result->detections, nullptr); + + VerifyDetection( + detection_result->detections[0], + {.origin_x = 54, .origin_y = 396, .width = 393, .height = 196}, + 0.64453125, "cat"); + VerifyDetection( + detection_result->detections[1], + {.origin_x = 602, .origin_y = 157, .width = 394, .height = 447}, + 0.59765625, "cat"); + VerifyDetection( + detection_result->detections[2], + {.origin_x = 261, .origin_y = 394, .width = 179, .height = 209}, 0.5625, + "cat"); + VerifyDetection( + detection_result->detections[3], + {.origin_x = 389, .origin_y = 197, .width = 276, .height = 409}, + 0.51171875, "dog"); +} + +class ObjectDetectorFromOptionsTest : public tflite_shims::testing::Test {}; + +TEST_F(ObjectDetectorFromOptionsTest, FailsWithNullOptionsAndError) { + TfLiteSupportError* error = nullptr; + TfLiteObjectDetector* object_detector = + TfLiteObjectDetectorFromOptions(nullptr, &error); + + EXPECT_EQ(object_detector, nullptr); + if (object_detector) + TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); + EXPECT_NE(error->message, nullptr); + EXPECT_THAT(error->message, HasSubstr("Expected non null options")); + + TfLiteSupportErrorDelete(error); +} + +TEST_F(ObjectDetectorFromOptionsTest, FailsWithMissingModelPath) { + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + TfLiteObjectDetector* object_detector = + TfLiteObjectDetectorFromOptions(&options, nullptr); + EXPECT_EQ(object_detector, nullptr); + if (object_detector) + TfLiteObjectDetectorDelete(object_detector); +} + +TEST_F(ObjectDetectorFromOptionsTest, FailsWithMissingModelPathAndError) { + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + + TfLiteSupportError* error = nullptr; + TfLiteObjectDetector* object_detector = + TfLiteObjectDetectorFromOptions(&options, &error); + + EXPECT_EQ(object_detector, nullptr); + if (object_detector) + TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); + EXPECT_NE(error->message, nullptr); + EXPECT_THAT(error->message, HasSubstr("`base_options.model_file`")); + + TfLiteSupportErrorDelete(error); +} + +TEST_F(ObjectDetectorFromOptionsTest, SucceedsWithModelPath) { + std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, + kMobileSsdWithMetadata); + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); + TfLiteObjectDetector* object_detector = + TfLiteObjectDetectorFromOptions(&options, nullptr); + + EXPECT_NE(object_detector, nullptr); + TfLiteObjectDetectorDelete(object_detector); +} + +TEST_F(ObjectDetectorFromOptionsTest, SucceedsWithNumberOfThreadsAndError) { + std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, + kMobileSsdWithMetadata); + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); + options.base_options.compute_settings.cpu_settings.num_threads = 3; + + TfLiteSupportError* error = nullptr; + TfLiteObjectDetector* object_detector = + TfLiteObjectDetectorFromOptions(&options, &error); + + EXPECT_NE(object_detector, nullptr); + EXPECT_EQ(error, nullptr); + + if (object_detector) + TfLiteObjectDetectorDelete(object_detector); + if (error) + TfLiteSupportErrorDelete(error); +} + +TEST_F(ObjectDetectorFromOptionsTest, + FailsWithClassNameDenyListAndClassNameAllowListAndError) { + std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, + kMobileSsdWithMetadata); + + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); + + char* label_denylist[9] = {(char*)"cat"}; + options.classification_options.label_denylist.list = label_denylist; + options.classification_options.label_denylist.length = 1; + + char* label_allowlist[12] = {(char*)"dog"}; + options.classification_options.label_allowlist.list = label_allowlist; + options.classification_options.label_allowlist.length = 1; + + TfLiteSupportError* error = nullptr; + TfLiteObjectDetector* object_detector = + TfLiteObjectDetectorFromOptions(&options, &error); + + EXPECT_EQ(object_detector, nullptr); + if (object_detector) + TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); + EXPECT_NE(error->message, nullptr); + EXPECT_THAT(error->message, HasSubstr("mutually exclusive options")); + + TfLiteSupportErrorDelete(error); +} + +TEST(ObjectDetectorNullDetectorDetectTest, + FailsWithNullObjectDetectorAndError) { + SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, + LoadImage("cats_and_dogs.jpg")); + + TfLiteSupportError* error = nullptr; + TfLiteDetectionResult* detection_result = + TfLiteObjectDetectorDetect(nullptr, nullptr, &error); + + ImageDataFree(&image_data); + + EXPECT_EQ(detection_result, nullptr); + if (detection_result) + TfLiteDetectionResultDelete(detection_result); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); + EXPECT_NE(error->message, nullptr); + EXPECT_THAT(error->message, HasSubstr("Expected non null object detector.")); + + TfLiteSupportErrorDelete(error); +} + +class ObjectDetectorDetectTest : public tflite_shims::testing::Test { + protected: + void SetUp() override { + std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, + kMobileSsdWithMetadata); + + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); + object_detector = TfLiteObjectDetectorFromOptions(&options, nullptr); + ASSERT_NE(object_detector, nullptr); + } + + void TearDown() override { TfLiteObjectDetectorDelete(object_detector); } + TfLiteObjectDetector* object_detector; +}; + +TEST_F(ObjectDetectorDetectTest, SucceedsWithImageData) { + SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, + LoadImage("cats_and_dogs.jpg")); + + TfLiteFrameBuffer frame_buffer = { + .format = kRGB, + .orientation = kTopLeft, + .dimension = {.width = image_data.width, .height = image_data.height}, + .buffer = image_data.pixel_data}; + + TfLiteDetectionResult* detection_result = + TfLiteObjectDetectorDetect(object_detector, &frame_buffer, nullptr); + + ImageDataFree(&image_data); + + VerifyResults(detection_result); + + TfLiteDetectionResultDelete(detection_result); +} + +TEST_F(ObjectDetectorDetectTest, FailsWithNullFrameBufferAndError) { + SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, + LoadImage("cats_and_dogs.jpg")); + + TfLiteSupportError* error = nullptr; + TfLiteDetectionResult* detection_result = + TfLiteObjectDetectorDetect(object_detector, nullptr, &error); + + ImageDataFree(&image_data); + + EXPECT_EQ(detection_result, nullptr); + if (detection_result) + TfLiteDetectionResultDelete(detection_result); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); + EXPECT_NE(error->message, nullptr); + EXPECT_THAT(error->message, HasSubstr("Expected non null frame buffer")); + + TfLiteSupportErrorDelete(error); +} + +TEST_F(ObjectDetectorDetectTest, FailsWithNullImageDataAndError) { + SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, + LoadImage("cats_and_dogs.jpg")); + TfLiteSupportError* error = nullptr; + TfLiteDetectionResult* detection_result = + TfLiteObjectDetectorDetect(object_detector, nullptr, &error); + + ImageDataFree(&image_data); + + EXPECT_EQ(detection_result, nullptr); + if (detection_result) + TfLiteDetectionResultDelete(detection_result); + + ASSERT_NE(error, nullptr); + EXPECT_EQ(error->code, kInvalidArgumentError); + EXPECT_NE(error->message, nullptr); + EXPECT_THAT(error->message, HasSubstr("INVALID_ARGUMENT")); + + TfLiteSupportErrorDelete(error); +} + +TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + SucceedsWithClassNameDenyList) { + char* denylisted_label_name = (char*)"cat"; + std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, + kMobileSsdWithMetadata); + + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); + + char* label_denylist[12] = {denylisted_label_name}; + options.classification_options.label_denylist.list = label_denylist; + options.classification_options.label_denylist.length = 1; + + TfLiteObjectDetector* object_detector = + TfLiteObjectDetectorFromOptions(&options, nullptr); + ASSERT_NE(object_detector, nullptr); + + SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, + LoadImage("cats_and_dogs.jpg")); + + TfLiteFrameBuffer frame_buffer = { + .format = kRGB, + .orientation = kTopLeft, + .dimension = {.width = image_data.width, .height = image_data.height}, + .buffer = image_data.pixel_data}; + + TfLiteDetectionResult* detection_result = + TfLiteObjectDetectorDetect(object_detector, &frame_buffer, nullptr); + + ImageDataFree(&image_data); + if (object_detector) + TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(detection_result, nullptr); + EXPECT_GE(detection_result->size, 1); + EXPECT_NE(detection_result->detections, nullptr); + EXPECT_GE(detection_result->detections->size, 1); + EXPECT_NE(detection_result->detections[0].categories, nullptr); + EXPECT_THAT(detection_result->detections[0].categories[0].label, + StrNe(denylisted_label_name)); + + TfLiteDetectionResultDelete(detection_result); +} + +TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + SucceedsWithClassNameAllowList) { + char* allowlisted_label_name = (char*)"cat"; + std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, + kMobileSsdWithMetadata) + .data(); + + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); + + char* label_allowlist[12] = {allowlisted_label_name}; + options.classification_options.label_allowlist.list = label_allowlist; + options.classification_options.label_allowlist.length = 1; + + TfLiteObjectDetector* object_detector = + TfLiteObjectDetectorFromOptions(&options, nullptr); + ASSERT_NE(object_detector, nullptr); + + SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, + LoadImage("cats_and_dogs.jpg")); + + TfLiteFrameBuffer frame_buffer = { + .format = kRGB, + .orientation = kTopLeft, + .dimension = {.width = image_data.width, .height = image_data.height}, + .buffer = image_data.pixel_data}; + + TfLiteDetectionResult* detection_result = + TfLiteObjectDetectorDetect(object_detector, &frame_buffer, nullptr); + + ImageDataFree(&image_data); + if (object_detector) + TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(detection_result, nullptr); + EXPECT_GE(detection_result->size, 1); + EXPECT_NE(detection_result->detections, nullptr); + EXPECT_GE(detection_result->detections->size, 1); + EXPECT_NE(detection_result->detections[0].categories, nullptr); + EXPECT_THAT(detection_result->detections[0].categories[0].label, + StrEq(allowlisted_label_name)); + + TfLiteDetectionResultDelete(detection_result); +} + +TEST(ObjectDetectorWithUserDefinedOptionsDetectorTest, + SucceedsWithScoreThreshold) { + std::string model_path = JoinPath("./" /*test src dir*/, kTestDataDirectory, + kMobileSsdWithMetadata) + .data(); + + TfLiteObjectDetectorOptions options = TfLiteObjectDetectorOptionsCreate(); + options.base_options.model_file.file_path = model_path.data(); + + options.classification_options.score_threshold = 0.6; + + TfLiteObjectDetector* object_detector = + TfLiteObjectDetectorFromOptions(&options, nullptr); + ASSERT_NE(object_detector, nullptr); + + SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData image_data, + LoadImage("cats_and_dogs.jpg")); + + TfLiteFrameBuffer frame_buffer = { + .format = kRGB, + .orientation = kTopLeft, + .dimension = {.width = image_data.width, .height = image_data.height}, + .buffer = image_data.pixel_data}; + + TfLiteDetectionResult* detection_result = + TfLiteObjectDetectorDetect(object_detector, &frame_buffer, nullptr); + + ImageDataFree(&image_data); + if (object_detector) + TfLiteObjectDetectorDelete(object_detector); + + ASSERT_NE(detection_result, nullptr); + EXPECT_EQ(detection_result->size, 1); + EXPECT_NE(detection_result->detections, nullptr); + VerifyDetection( + detection_result->detections[0], + {.origin_x = 54, .origin_y = 396, .width = 393, .height = 196}, + 0.64453125, "cat"); + + TfLiteDetectionResultDelete(detection_result); +} + +} // namespace +} // namespace vision +} // namespace task +} // namespace tflite
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/port/build_defs.bzl b/third_party/tflite_support/src/tensorflow_lite_support/cc/port/build_defs.bzl index 73fbb5f..055cacd 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/port/build_defs.bzl +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/port/build_defs.bzl
@@ -1,5 +1,7 @@ """.bzl file for TFLite Support open source build configs.""" +load("@com_google_protobuf//:protobuf.bzl", "py_proto_library") + def provided_args(**kwargs): """Returns the keyword arguments omitting None arguments.""" return {k: v for k, v in kwargs.items() if v != None} @@ -20,3 +22,33 @@ visibility = visibility, deps = deps, )) + +def support_py_proto_library( + name, + srcs, + visibility = None, + py_proto_deps = [], + proto_deps = None, + api_version = None, + testonly = 0): + """Generates py_proto_library for TFLite Support open source version. + + Args: + name: the name of the py_proto_library. + api_version: api version for internal use only. + srcs: the .proto files of the py_proto_library for Bazel use. + visibility: visibility of this target. + py_proto_deps: a list of dependency labels for Bazel use; must be py_proto_library. + proto_deps: a list of dependency labels for internal use. + testonly: test only proto or not. + """ + _ignore = [api_version, proto_deps] + py_proto_library(**provided_args( + name = name, + srcs = srcs, + visibility = visibility, + default_runtime = "@com_google_protobuf//:protobuf_python", + protoc = "@com_google_protobuf//:protoc", + deps = py_proto_deps + ["@com_google_protobuf//:protobuf_python"], + testonly = testonly, + ))
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.cc index 0b3e5d6a..bb43d09f 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.cc
@@ -40,7 +40,8 @@ Delegate delegate = compute_settings.tflite_settings().delegate(); if (delegate != Delegate::NONE && delegate != Delegate::GPU && delegate != Delegate::HEXAGON && delegate != Delegate::NNAPI && - delegate != Delegate::XNNPACK && delegate != Delegate::EDGETPU_CORAL) { + delegate != Delegate::XNNPACK && delegate != Delegate::EDGETPU_CORAL && + delegate != Delegate::CORE_ML) { return absl::UnimplementedError(absl::StrFormat( "Using delegate '%s' is not supported.", Delegate_Name(delegate))); } @@ -245,6 +246,9 @@ } else if (which_delegate == Delegate::XNNPACK) { RETURN_IF_ERROR( LoadDelegatePlugin("XNNPack", *compute_settings->tflite_settings())); + } else if (which_delegate == Delegate::CORE_ML) { + RETURN_IF_ERROR( + LoadDelegatePlugin("CoreML", *compute_settings->tflite_settings())); } } return absl::OkStatus();
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.h index 9f32fa8..a9deed9 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/port/default/tflite_wrapper.h
@@ -72,8 +72,8 @@ // performant acceleration for the case where input size changes frequently. // // IMPORTANT: The only supported delegates are (as defined in [1]) NONE, GPU, -// HEXAGON and NNAPI. Trying to use this class with EDGETPU or XNNPACK delegates -// will cause an UnimplementedError to be thrown at initialization time. +// HEXAGON, NNAPI, EDGETPU (Google internal), and EDGETPU_CORAL. Specifying +// another delegate type may cause an UnimplementedError to be thrown. // // Like TfLiteInterpreter, this class is thread-compatible. Use from multiple // threads must be guarded by synchronization outside this class. @@ -106,10 +106,6 @@ // This flag allows callers to rely on this function whether or not they // actually want fallback to happen; if they don't, it will ensure that the // configuration doesn't accidentally trigger fallback. - // - // IMPORTANT: Supported delegate type includes: NONE, NNAPI, GPU, HEXAGON, - // XNNPACK, EDGETPU (Google internal), and EDGETPU_CORAL. Specifying another - // delegate type may cause an UnimplementedError to be thrown. absl::Status InitializeWithFallback( std::function<absl::Status(const InterpreterCreationResources&, std::unique_ptr<tflite::Interpreter>*)>
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/audio/proto/audio_embedder_options.proto b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/audio/proto/audio_embedder_options.proto index 0271c2f4..e60a460 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/audio/proto/audio_embedder_options.proto +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/audio/proto/audio_embedder_options.proto
@@ -1,4 +1,3 @@ - /* Copyright 2021 The TensorFlow Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License");
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/BUILD index 46a16bd..88350e59 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/BUILD
@@ -64,6 +64,7 @@ cc_library_with_tflite( name = "task_api_factory", + srcs = ["task_api_factory.cc"], hdrs = ["task_api_factory.h"], tflite_deps = [ ":base_task_api",
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/BUILD index 6c97e2b..821df9b63 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/BUILD
@@ -1,4 +1,4 @@ -load("//tensorflow_lite_support/cc/port:build_defs.bzl", "support_cc_proto_library") +load("//tensorflow_lite_support/cc/port:build_defs.bzl", "support_cc_proto_library", "support_py_proto_library") package( default_visibility = [ @@ -19,6 +19,13 @@ ], ) +support_py_proto_library( + name = "external_file_py_pb2", + srcs = ["external_file.proto"], + api_version = 2, + proto_deps = [":external_file_proto"], +) + cc_library( name = "external_file_proto_inc", hdrs = ["external_file_proto_inc.h"], @@ -41,6 +48,17 @@ ], ) +support_py_proto_library( + name = "base_options_py_pb2", + srcs = ["base_options.proto"], + api_version = 2, + proto_deps = [":base_options_proto"], + py_proto_deps = [ + "@org_tensorflow//tensorflow/lite/experimental/acceleration/configuration:configuration_proto_external_py", + "//tensorflow_lite_support/cc/task/core/proto:external_file_py_pb2", + ], +) + cc_library( name = "base_options_proto_inc", hdrs = ["base_options_proto_inc.h"], @@ -77,3 +95,8 @@ ":class_proto", ], ) + +java_lite_proto_library( + name = "base_options_java_proto_lite", + deps = [":base_options_proto"], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/base_options.proto b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/base_options.proto index 9d529d6..7b71fcc 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/base_options.proto +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/base_options.proto
@@ -21,6 +21,9 @@ import "tensorflow_lite_support/cc/task/core/proto/external_file.proto"; +option java_multiple_files = true; +option java_package = "org.tensorflow.lite.task.core.proto"; + // Base options for task libraries. // Next Id: 4 message BaseOptions {
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/external_file.proto b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/external_file.proto index 91b6a214..c0a4212 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/external_file.proto +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/proto/external_file.proto
@@ -17,6 +17,7 @@ package tflite.task.core; + // Represents external files used by the Task APIs (e.g. TF Lite FlatBuffer or // plain-text labels file). The files can be specified by one of the following // three ways: @@ -63,3 +64,4 @@ // offset of a given asset obtained from AssetFileDescriptor#getStartOffset(). optional int64 offset = 3; } +
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_api_factory.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_api_factory.cc new file mode 100644 index 0000000..8ee59bfa --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_api_factory.cc
@@ -0,0 +1,57 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow_lite_support/cc/task/core/task_api_factory.h" + +namespace tflite { +namespace task { +namespace core { + +// static +absl::Status TaskAPIFactory::SetMiniBenchmarkFileNameFromBaseOptions( + ::tflite::proto::ComputeSettings& compute_settings, + const BaseOptions* base_options) { + if (!base_options->has_model_file()) { + return CreateStatusWithPayload( + absl::StatusCode::kInvalidArgument, + "Missing mandatory `model_file` field in `base_options`", + tflite::support::TfLiteSupportStatus::kInvalidArgumentError); + } + if (base_options->model_file().has_file_name()) { + compute_settings.mutable_settings_to_test_locally() + ->mutable_model_file() + ->set_filename(base_options->model_file().file_name()); + } else if (base_options->model_file().has_file_descriptor_meta()) { + const task::core::FileDescriptorMeta& fd_meta = + base_options->model_file().file_descriptor_meta(); + auto* mutable_model_file = + compute_settings.mutable_settings_to_test_locally() + ->mutable_model_file(); + mutable_model_file->set_fd(fd_meta.fd()); + mutable_model_file->set_offset(fd_meta.offset()); + mutable_model_file->set_length(fd_meta.length()); + } else { + return CreateStatusWithPayload( + absl::StatusCode::kInvalidArgument, + "Mini-benchmark is currently not able to run on model passed as " + "bytes.", + tflite::support::TfLiteSupportStatus::kInvalidArgumentError); + } + + return absl::OkStatus(); +} + +} // namespace core +} // namespace task +} // namespace tflite
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_api_factory.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_api_factory.h index f42d703f..bbe549a 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_api_factory.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_api_factory.h
@@ -143,10 +143,15 @@ } auto engine = absl::make_unique<TfLiteEngine>(std::move(resolver)); + tflite::proto::ComputeSettings compute_settings( + base_options->compute_settings()); + if (compute_settings.has_settings_to_test_locally()) { + RETURN_IF_ERROR(SetMiniBenchmarkFileNameFromBaseOptions(compute_settings, + base_options)); + } RETURN_IF_ERROR(engine->BuildModelFromExternalFileProto( - &base_options->model_file(), base_options->compute_settings())); - return CreateFromTfLiteEngine<T>(std::move(engine), - base_options->compute_settings()); + &base_options->model_file(), compute_settings)); + return CreateFromTfLiteEngine<T>(std::move(engine), compute_settings); } private: @@ -172,6 +177,10 @@ RETURN_IF_ERROR(engine->InitInterpreter(compute_settings)); return absl::make_unique<T>(std::move(engine)); } + + static absl::Status SetMiniBenchmarkFileNameFromBaseOptions( + tflite::proto::ComputeSettings& compute_settings, + const BaseOptions* base_options); }; } // namespace core
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.cc index e40c2ac..d4565c3 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.cc
@@ -61,15 +61,15 @@ return buffer; } -int FindIndexByMetadataTensorName( +int FindTensorIndexByMetadataName( const flatbuffers::Vector<flatbuffers::Offset<TensorMetadata>>* tensor_metadatas, - const std::string& name) { + absl::string_view name) { if (tensor_metadatas == nullptr) { return -1; } for (int i = 0; i < tensor_metadatas->size(); i++) { - if (strcmp(name.data(), tensor_metadatas->Get(i)->name()->c_str()) == 0) { + if (name == tensor_metadatas->Get(i)->name()->c_str()) { return i; } }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h index 7cde474..43a508ae 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/core/task_utils.h
@@ -21,11 +21,12 @@ #include <numeric> #include <vector> -#include "absl/memory/memory.h" // from @com_google_absl -#include "absl/status/status.h" // from @com_google_absl -#include "absl/strings/str_cat.h" // from @com_google_absl -#include "absl/strings/str_format.h" // from @com_google_absl -#include "flatbuffers/flatbuffers.h" // from @flatbuffers +#include "absl/memory/memory.h" // from @com_google_absl +#include "absl/status/status.h" // from @com_google_absl +#include "absl/strings/str_cat.h" // from @com_google_absl +#include "absl/strings/str_format.h" // from @com_google_absl +#include "absl/strings/string_view.h" // from @com_google_absl +#include "flatbuffers/flatbuffers.h" // from @flatbuffers #include "tensorflow/lite/kernels/internal/tensor_ctypes.h" #include "tensorflow/lite/kernels/op_macros.h" #include "tensorflow/lite/string_util.h" @@ -203,27 +204,63 @@ // Loads binary content of a file into a string. std::string LoadBinaryContent(const char* filename); -// Gets the index from a vector of tensors with name specified inside metadata. -// The range of the return value should be [0, output_tensor_size). If not -// found, returns -1. -int FindIndexByMetadataTensorName( +// Finds the tensor index of the specified tensor name from a vector of tensors +// by checking the metadata tensor name. +// The range of the return value should be [0, tensor_size). Return -1 if no +// tensor is found by name. +int FindTensorIndexByMetadataName( const flatbuffers::Vector<flatbuffers::Offset<TensorMetadata>>* - tensor_metadatas, - const std::string& name); + tensor_metadata, + absl::string_view name); -// Gets the tensor from a vector of tensors with name specified inside metadata. +// Finds the tensor index of the specified tensor name from a vector of tensors +// by checking the model tensor name. +// The range of the return value should be [0, tensor_size). Return -1 if no +// tensor is found by name. +template <typename TensorType> +int FindTensorIndexByModelName(const std::vector<TensorType*>& tensors, + absl::string_view name) { + for (int i = 0; i < tensors.size(); i++) { + TensorType* tensor = tensors[i]; + if (tensor->name == name) { + return i; + } + } + return -1; +} + +// Finds the tensor index of the specified tensor name from a vector of tensors +// by first checking the metadata tensor name, and then the model tensor name. +// The range of the return value should be [0, tensor_size). Return -1 if no +// tensor is found by name. +template <typename TensorType> +int FindTensorIndexByName( + const std::vector<TensorType*>& tensors, + const flatbuffers::Vector<flatbuffers::Offset<TensorMetadata>>* + tensor_metadata, + absl::string_view metadata_tensor_name, + absl::string_view model_tensor_name) { + if (tensor_metadata != nullptr && tensor_metadata->size() == tensors.size()) { + int index = + FindTensorIndexByMetadataName(tensor_metadata, metadata_tensor_name); + if (index > -1) + return index; + } + + return FindTensorIndexByModelName(tensors, model_tensor_name); +} + +// Finds the tensor from a vector of tensors with name specified inside +// metadata. template <typename TensorType> static TensorType* FindTensorByName( const std::vector<TensorType*>& tensors, const flatbuffers::Vector<flatbuffers::Offset<TensorMetadata>>* - tensor_metadatas, - const std::string& name) { - if (tensor_metadatas == nullptr || - tensor_metadatas->size() != tensors.size()) { - return nullptr; - } - int i = FindIndexByMetadataTensorName(tensor_metadatas, name); - return i == -1 ? nullptr : tensors[i]; + tensor_metadata, + absl::string_view metadata_tensor_name) { + int index = FindTensorIndexByName(tensors, tensor_metadata, + metadata_tensor_name, absl::string_view()); + return index == -1 ? nullptr : tensors[index]; } } // namespace core
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/bert_preprocessor.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/bert_preprocessor.cc index 96c5e0d..8420deb 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/bert_preprocessor.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/bert_preprocessor.cc
@@ -32,7 +32,7 @@ using ::tflite::support::TfLiteSupportStatus; using ::tflite::support::text::tokenizer::CreateTokenizerFromProcessUnit; using ::tflite::support::text::tokenizer::TokenizerResult; -using ::tflite::task::core::FindIndexByMetadataTensorName; +using ::tflite::task::core::FindTensorIndexByMetadataName; using ::tflite::task::core::PopulateTensor; constexpr int kTokenizerProcessUnitIndex = 0; @@ -63,15 +63,15 @@ // Identify the tensor index for three Bert input tensors. auto tensors_metadata = GetMetadataExtractor()->GetInputTensorMetadata(); int ids_tensor_index = - FindIndexByMetadataTensorName(tensors_metadata, kIdsTensorName); + FindTensorIndexByMetadataName(tensors_metadata, kIdsTensorName); ids_tensor_index_ = ids_tensor_index == -1 ? tensor_indices_[0] : ids_tensor_index; int mask_tensor_index = - FindIndexByMetadataTensorName(tensors_metadata, kMaskTensorName); + FindTensorIndexByMetadataName(tensors_metadata, kMaskTensorName); mask_tensor_index_ = mask_tensor_index == -1 ? tensor_indices_[1] : mask_tensor_index; int segment_ids_tensor_index = - FindIndexByMetadataTensorName(tensors_metadata, kSegmentIdsTensorName); + FindTensorIndexByMetadataName(tensors_metadata, kSegmentIdsTensorName); segment_ids_tensor_index_ = segment_ids_tensor_index == -1 ? tensor_indices_[2] : segment_ids_tensor_index;
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/embedding_postprocessor.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/embedding_postprocessor.h index 78cef8ab5..f04048d 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/embedding_postprocessor.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/embedding_postprocessor.h
@@ -15,7 +15,9 @@ #ifndef TENSORFLOW_LITE_SUPPORT_CC_TASK_PROCESSOR_EMBEDDING_POSTPROCESSOR_H_ #define TENSORFLOW_LITE_SUPPORT_CC_TASK_PROCESSOR_EMBEDDING_POSTPROCESSOR_H_ + #include <initializer_list> +#include <memory> #include "absl/status/status.h" // from @com_google_absl #include "tensorflow_lite_support/cc/port/status_macros.h" @@ -38,7 +40,8 @@ static tflite::support::StatusOr<std::unique_ptr<EmbeddingPostprocessor>> Create(core::TfLiteEngine* engine, const std::initializer_list<int> output_indices, - std::unique_ptr<EmbeddingOptions> options); + std::unique_ptr<EmbeddingOptions> options = + std::make_unique<EmbeddingOptions>()); template <typename T> absl::Status Postprocess(T* embedding);
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/BUILD index 7e1e203..996467c 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/BUILD
@@ -1,3 +1,5 @@ +load("//tensorflow_lite_support/cc/port:build_defs.bzl", "support_py_proto_library") + package( default_visibility = [ "//visibility:public", @@ -54,6 +56,13 @@ ], ) +support_py_proto_library( + name = "embedding_options_py_pb2", + srcs = ["embedding_options.proto"], + api_version = 2, + proto_deps = [":embedding_options_proto"], +) + proto_library( name = "classification_options_proto", srcs = ["classification_options.proto"], @@ -65,3 +74,13 @@ ":classification_options_proto", ], ) + +java_lite_proto_library( + name = "classification_options_java_proto_lite", + deps = [":classification_options_proto"], +) + +java_lite_proto_library( + name = "embedding_options_java_proto_lite", + deps = [":embedding_options_proto"], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/classification_options.proto b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/classification_options.proto index 0546800..01bcd6f 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/classification_options.proto +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/classification_options.proto
@@ -17,6 +17,9 @@ package tflite.task.processor; +option java_multiple_files = true; +option java_package = "org.tensorflow.lite.task.processor.proto"; + // Options for classification processor. // Next Id: 6 message ClassificationOptions {
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/embedding_options.proto b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/embedding_options.proto index 28bd2e11..d4c24a7 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/embedding_options.proto +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/embedding_options.proto
@@ -17,6 +17,9 @@ package tflite.task.processor; +option java_multiple_files = true; +option java_package = "org.tensorflow.lite.task.processor.proto"; + // Options for embedding processor. // Next Id: 3 message EmbeddingOptions {
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/search_result.proto b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/search_result.proto new file mode 100644 index 0000000..06014138 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/proto/search_result.proto
@@ -0,0 +1,39 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +syntax = "proto2"; + +package tflite.task.processor; + +option java_multiple_files = true; +option java_package = "org.tensorflow.lite.task.processor.proto"; + +// A single nearest neighbor. +// Next ID: 3. +message NearestNeighbor { + // User-defined metadata about the result. This could be a label, a unique ID, + // a serialized proto of some sort, etc. + optional bytes metadata = 1; + + // The distance score indicating how confident the result is. Lower is better. + optional float distance = 2; +} + +// Results from a search as a list of nearest neigbors. +// Next ID: 2. +message SearchResult { + // The nearest neighbors, sorted by increasing distance order. + repeated NearestNeighbor nearest_neighbors = 1; +}
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/text_preprocessor.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/text_preprocessor.cc index 30525229..fc2f2f73 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/text_preprocessor.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/text_preprocessor.cc
@@ -29,7 +29,6 @@ using ::absl::StatusCode; using ::tflite::support::CreateStatusWithPayload; using ::tflite::support::StatusOr; -using ::tflite::support::TfLiteSupportStatus; } // namespace @@ -46,7 +45,7 @@ return CreateStatusWithPayload( StatusCode::kInvalidArgument, absl::StrFormat( - "TextPrerocessor accepts either 1 input tesnor (for Regex " + "TextPreprocessor accepts either 1 input tensor (for Regex " "tokenizer or String tensor) or 3 input tensors (for Bert " "tokenizer), but got %d tensors.", input_tensor_indices.size()));
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/text_preprocessor.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/text_preprocessor.h index 5781bf4..f292ba42 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/text_preprocessor.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/processor/text_preprocessor.h
@@ -43,7 +43,7 @@ tflite::task::core::TfLiteEngine* engine, const std::initializer_list<int> input_tensor_indices); - absl::Status Preprocess(const std::string& text); + virtual absl::Status Preprocess(const std::string& text) = 0; protected: using Preprocessor::Preprocessor;
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/BUILD index 05b7c5e..67581ac2 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/BUILD
@@ -20,6 +20,7 @@ "//tensorflow_lite_support/cc/task/text/nlclassifier:nl_classifier", "@org_tensorflow//tensorflow/lite/core/shims:builtin_ops", "//tensorflow_lite_support/cc/task/core:task_api_factory", + "//tensorflow_lite_support/cc/task/processor:bert_preprocessor", ], deps = [ "//tensorflow_lite_support/cc:common", @@ -27,13 +28,8 @@ "//tensorflow_lite_support/cc/task/core:category", "//tensorflow_lite_support/cc/task/core:task_utils", "//tensorflow_lite_support/cc/task/text/proto:bert_nl_classifier_options_proto_inc", - "//tensorflow_lite_support/cc/text/tokenizers:tokenizer", - "//tensorflow_lite_support/cc/text/tokenizers:tokenizer_utils", - "//tensorflow_lite_support/metadata/cc:metadata_extractor", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status", - "@com_google_absl//absl/strings", - "@com_google_absl//absl/strings:str_format", "@org_tensorflow//tensorflow/lite:string", "@org_tensorflow//tensorflow/lite/c:common", "@org_tensorflow//tensorflow/lite/core/api", @@ -98,19 +94,41 @@ "//tensorflow_lite_support/cc/task/core:tflite_engine", ], deps = [ - "//tensorflow_lite_support/cc/port:status_macros", "//tensorflow_lite_support/cc/port:statusor", "//tensorflow_lite_support/cc/task/core:task_utils", "//tensorflow_lite_support/cc/task/processor/proto:embedding_cc_proto", "//tensorflow_lite_support/cc/task/text/proto:retrieval_cc_proto", - "//tensorflow_lite_support/cc/text/tokenizers:bert_tokenizer", - "//tensorflow_lite_support/cc/text/tokenizers:sentencepiece_tokenizer", - "//tensorflow_lite_support/cc/text/tokenizers:tokenizer", - "//tensorflow_lite_support/cc/text/tokenizers:tokenizer_utils", - "//tensorflow_lite_support/metadata:metadata_schema_cc", "@com_google_absl//absl/container:flat_hash_map", "@com_google_absl//absl/status", - "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format", ], ) + +cc_library_with_tflite( + name = "text_embedder", + srcs = [ + "text_embedder.cc", + ], + hdrs = [ + "text_embedder.h", + ], + tflite_deps = [ + "@org_tensorflow//tensorflow/lite/core/shims:builtin_ops", + "//tensorflow_lite_support/cc/task/core:base_task_api", + "//tensorflow_lite_support/cc/task/core:task_api_factory", + "//tensorflow_lite_support/cc/task/processor:embedding_postprocessor", + "//tensorflow_lite_support/cc/task/processor:text_preprocessor", + "//tensorflow_lite_support/cc/task/processor:bert_preprocessor", + "//tensorflow_lite_support/cc/task/processor:regex_preprocessor", + ], + deps = [ + "//tensorflow_lite_support/cc:common", + "//tensorflow_lite_support/cc/port:status_macros", + "//tensorflow_lite_support/cc/port:statusor", + "//tensorflow_lite_support/cc/task/processor/proto:embedding_cc_proto", + "//tensorflow_lite_support/cc/task/processor/proto:embedding_options_cc_proto", + "//tensorflow_lite_support/cc/task/text/proto:text_embedder_options_cc_proto", + "@com_google_absl//absl/status", + "@org_tensorflow//tensorflow/lite/core/api:op_resolver", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.cc index ac8fa548..7de37f1 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.cc
@@ -23,21 +23,15 @@ #include <utility> #include <vector> -#include "absl/status/status.h" // from @com_google_absl -#include "absl/strings/ascii.h" // from @com_google_absl -#include "absl/strings/str_format.h" // from @com_google_absl +#include "absl/status/status.h" // from @com_google_absl #include "tensorflow/lite/c/common.h" #include "tensorflow/lite/core/api/op_resolver.h" -#include "tensorflow/lite/string_type.h" #include "tensorflow_lite_support/cc/common.h" #include "tensorflow_lite_support/cc/port/status_macros.h" #include "tensorflow_lite_support/cc/task/core/category.h" #include "tensorflow_lite_support/cc/task/core/task_api_factory.h" #include "tensorflow_lite_support/cc/task/core/task_utils.h" #include "tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h" -#include "tensorflow_lite_support/cc/text/tokenizers/tokenizer.h" -#include "tensorflow_lite_support/cc/text/tokenizers/tokenizer_utils.h" -#include "tensorflow_lite_support/metadata/cc/metadata_extractor.h" namespace tflite { namespace task { @@ -46,19 +40,10 @@ using ::tflite::support::CreateStatusWithPayload; using ::tflite::support::StatusOr; using ::tflite::support::TfLiteSupportStatus; -using ::tflite::support::text::tokenizer::CreateTokenizerFromProcessUnit; -using ::tflite::support::text::tokenizer::TokenizerResult; using ::tflite::task::core::FindTensorByName; -using ::tflite::task::core::PopulateTensor; namespace { -constexpr char kIdsTensorName[] = "ids"; -constexpr char kMaskTensorName[] = "mask"; -constexpr char kSegmentIdsTensorName[] = "segment_ids"; constexpr char kScoreTensorName[] = "probability"; -constexpr char kClassificationToken[] = "[CLS]"; -constexpr char kSeparator[] = "[SEP]"; -constexpr int kTokenizerProcessUnitIndex = 0; absl::Status SanityCheckOptions(const BertNLClassifierOptions& options) { if (!options.has_base_options()) { @@ -68,81 +53,12 @@ } return absl::OkStatus(); } - -int GetLastDimSize(const TfLiteTensor* tensor) { - return tensor->dims->data[tensor->dims->size - 1]; -} - } // namespace absl::Status BertNLClassifier::Preprocess( const std::vector<TfLiteTensor*>& input_tensors, const std::string& input) { - auto* input_tensor_metadatas = - GetMetadataExtractor()->GetInputTensorMetadata(); - auto* ids_tensor = - FindTensorByName(input_tensors, input_tensor_metadatas, kIdsTensorName); - auto* mask_tensor = - FindTensorByName(input_tensors, input_tensor_metadatas, kMaskTensorName); - auto* segment_ids_tensor = FindTensorByName( - input_tensors, input_tensor_metadatas, kSegmentIdsTensorName); - - if (GetLastDimSize(ids_tensor) != GetLastDimSize(mask_tensor) || - GetLastDimSize(ids_tensor) != GetLastDimSize(segment_ids_tensor)) { - return CreateStatusWithPayload( - absl::StatusCode::kInternal, - absl::StrFormat("The three input tensors in BertNLClassifier models " - "are expected to have same length, but got ids_tensor " - "(%d), mask_tensor (%d), segment_ids_tensor (%d).", - GetLastDimSize(ids_tensor), GetLastDimSize(mask_tensor), - GetLastDimSize(ids_tensor)), - TfLiteSupportStatus::kInvalidNumOutputTensorsError); - } - - int max_seq_len = GetLastDimSize(ids_tensor); - - std::string processed_input = input; - absl::AsciiStrToLower(&processed_input); - - TokenizerResult input_tokenize_results; - input_tokenize_results = tokenizer_->Tokenize(processed_input); - - // 2 accounts for [CLS], [SEP] - absl::Span<const std::string> query_tokens = - absl::MakeSpan(input_tokenize_results.subwords.data(), - input_tokenize_results.subwords.data() + - std::min(static_cast<size_t>(max_seq_len - 2), - input_tokenize_results.subwords.size())); - - std::vector<std::string> tokens; - tokens.reserve(2 + query_tokens.size()); - // Start of generating the features. - tokens.push_back(kClassificationToken); - // For query input. - for (const auto& query_token : query_tokens) { - tokens.push_back(query_token); - } - // For Separation. - tokens.push_back(kSeparator); - - std::vector<int> input_ids(max_seq_len, 0); - std::vector<int> input_mask(max_seq_len, 0); - // Convert tokens back into ids and set mask - for (int i = 0; i < tokens.size(); ++i) { - tokenizer_->LookupId(tokens[i], &input_ids[i]); - input_mask[i] = 1; - } - // |<-----------max_seq_len--------->| - // input_ids [CLS] s1 s2... sn [SEP] 0 0... 0 - // input_masks 1 1 1... 1 1 0 0... 0 - // segment_ids 0 0 0... 0 0 0 0... 0 - - RETURN_IF_ERROR(PopulateTensor(input_ids, ids_tensor)); - RETURN_IF_ERROR(PopulateTensor(input_mask, mask_tensor)); - RETURN_IF_ERROR( - PopulateTensor(std::vector<int>(max_seq_len, 0), segment_ids_tensor)); - - return absl::OkStatus(); + return preprocessor_->Preprocess(input); } StatusOr<std::vector<core::Category>> BertNLClassifier::Postprocess( @@ -182,18 +98,10 @@ absl::Status BertNLClassifier::Initialize( std::unique_ptr<BertNLClassifierOptions> options) { options_ = std::move(options); - // Set up mandatory tokenizer from metadata. - const ProcessUnit* tokenizer_process_unit = - GetMetadataExtractor()->GetInputProcessUnit(kTokenizerProcessUnitIndex); - if (tokenizer_process_unit == nullptr) { - return CreateStatusWithPayload( - absl::StatusCode::kInvalidArgument, - "No input process unit found from metadata.", - TfLiteSupportStatus::kMetadataInvalidTokenizerError); - } - ASSIGN_OR_RETURN(tokenizer_, - CreateTokenizerFromProcessUnit(tokenizer_process_unit, - GetMetadataExtractor())); + + // Create preprocessor. + ASSIGN_OR_RETURN(preprocessor_, processor::BertPreprocessor::Create( + GetTfLiteEngine(), {0, 1, 2})); // Set up optional label vector from metadata. TrySetLabelFromMetadata(
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.h index 91bcfe5..bcc9c5a 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/bert_nl_classifier.h
@@ -29,9 +29,9 @@ #include "tensorflow/lite/core/shims/cc/kernels/register.h" #include "tensorflow/lite/string_type.h" #include "tensorflow_lite_support/cc/task/core/category.h" +#include "tensorflow_lite_support/cc/task/processor/bert_preprocessor.h" #include "tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h" #include "tensorflow_lite_support/cc/task/text/proto/bert_nl_classifier_options_proto_inc.h" -#include "tensorflow_lite_support/cc/text/tokenizers/tokenizer.h" namespace tflite { namespace task { @@ -121,7 +121,8 @@ // Initialize the API with the tokenizer and label files set in the metadata. absl::Status Initialize(std::unique_ptr<BertNLClassifierOptions> options); - std::unique_ptr<tflite::support::text::tokenizer::Tokenizer> tokenizer_; + std::unique_ptr<tflite::task::processor::BertPreprocessor> preprocessor_ = + nullptr; std::unique_ptr<BertNLClassifierOptions> options_; };
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/BUILD index 8a5ae2b..734f0ab 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/BUILD
@@ -20,6 +20,7 @@ "@org_tensorflow//tensorflow/lite/core/shims:builtin_ops", "//tensorflow_lite_support/cc/task/core:base_task_api", "//tensorflow_lite_support/cc/task/core:task_api_factory", + "//tensorflow_lite_support/cc/task/processor:regex_preprocessor", ], deps = [ "//tensorflow_lite_support/cc:common", @@ -28,10 +29,7 @@ "//tensorflow_lite_support/cc/task/core:category", "//tensorflow_lite_support/cc/task/core:task_utils", "//tensorflow_lite_support/cc/task/text/proto:nl_classifier_options_proto_inc", - "//tensorflow_lite_support/cc/text/tokenizers:regex_tokenizer", - "//tensorflow_lite_support/cc/text/tokenizers:tokenizer", "//tensorflow_lite_support/cc/utils:common_utils", - "//tensorflow_lite_support/metadata/cc:metadata_extractor", "@com_google_absl//absl/algorithm:container", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/status",
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.cc index 6986bcc..542d153c 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.cc
@@ -25,7 +25,7 @@ #include "absl/status/status.h" // from @com_google_absl #include "absl/strings/str_cat.h" // from @com_google_absl #include "absl/strings/string_view.h" // from @com_google_absl -#include "flatbuffers/flatbuffers.h" // from @flatbuffers +#include "flatbuffers/flatbuffers.h" // from @flatbuffers #include "tensorflow/lite/c/common.h" #include "tensorflow/lite/core/api/op_resolver.h" #include "tensorflow/lite/kernels/internal/tensor_ctypes.h" @@ -35,8 +35,6 @@ #include "tensorflow_lite_support/cc/task/core/category.h" #include "tensorflow_lite_support/cc/task/core/task_api_factory.h" #include "tensorflow_lite_support/cc/task/core/task_utils.h" -#include "tensorflow_lite_support/cc/text/tokenizers/regex_tokenizer.h" -#include "tensorflow_lite_support/cc/text/tokenizers/tokenizer.h" #include "tensorflow_lite_support/cc/utils/common_utils.h" namespace tflite { @@ -51,22 +49,16 @@ using ::tflite::support::CreateStatusWithPayload; using ::tflite::support::StatusOr; using ::tflite::support::TfLiteSupportStatus; -using ::tflite::support::text::tokenizer::RegexTokenizer; -using ::tflite::support::text::tokenizer::Tokenizer; -using ::tflite::support::text::tokenizer::TokenizerResult; using ::tflite::support::utils::LoadVocabFromBuffer; using ::tflite::task::core::Category; using ::tflite::task::core::Dequantize; using ::tflite::task::core::GetStringAtIndex; -using ::tflite::task::core::PopulateTensor; using ::tflite::task::core::TaskAPIFactory; // To differenciate it with the struct option, // tflite::task::text::nl_classifier::NLClassifierOptions. using NLClassifierProtoOptions = ::tflite::task::text::NLClassifierOptions; namespace { -constexpr int kRegexTokenizerInputTensorIndex = 0; -constexpr int kRegexTokenizerProcessUnitIndex = 0; absl::Status SanityCheckOptions(const NLClassifierProtoOptions& options) { if (!options.has_base_options()) { @@ -77,78 +69,6 @@ return absl::OkStatus(); } -StatusOr<absl::string_view> CheckAndLoadFirstAssociatedFile( - const flatbuffers::Vector<flatbuffers::Offset<tflite::AssociatedFile>>* - associated_files, - const tflite::metadata::ModelMetadataExtractor* metadata_extractor) { - if (associated_files == nullptr || associated_files->size() < 1 || - associated_files->Get(0)->name() == nullptr) { - return CreateStatusWithPayload( - absl::StatusCode::kInvalidArgument, - "Invalid vocab_file from input process unit.", - TfLiteSupportStatus::kMetadataInvalidTokenizerError); - } - ASSIGN_OR_RETURN(absl::string_view vocab_buffer, - metadata_extractor->GetAssociatedFile( - associated_files->Get(0)->name()->str())); - return vocab_buffer; -} - -StatusOr<std::unique_ptr<Tokenizer>> CreateRegexTokenizerFromProcessUnit( - const tflite::ProcessUnit* tokenizer_process_unit, - const tflite::metadata::ModelMetadataExtractor* metadata_extractor) { - if (metadata_extractor == nullptr || tokenizer_process_unit == nullptr) { - return CreateStatusWithPayload( - absl::StatusCode::kInvalidArgument, - "No metadata or input process unit found.", - TfLiteSupportStatus::kMetadataInvalidTokenizerError); - } - - if (tokenizer_process_unit->options_type() != - ProcessUnitOptions_RegexTokenizerOptions) { - return CreateStatusWithPayload( - absl::StatusCode::kNotFound, - absl::StrCat( - "Incorrect options_type:", tokenizer_process_unit->options_type(), - " need RegexTokenizerOptions."), - TfLiteSupportStatus::kMetadataInvalidTokenizerError); - } - - const tflite::RegexTokenizerOptions* options = - tokenizer_process_unit->options_as<RegexTokenizerOptions>(); - ASSIGN_OR_RETURN(absl::string_view vocab_buffer, - CheckAndLoadFirstAssociatedFile(options->vocab_file(), - metadata_extractor)); - if (options->delim_regex_pattern() == nullptr) { - return CreateStatusWithPayload( - absl::StatusCode::kInvalidArgument, - "Invalid delim_regex_pattern from input process unit.", - TfLiteSupportStatus::kMetadataInvalidTokenizerError); - } - - std::unique_ptr<RegexTokenizer> regex_tokenizer = - absl::make_unique<RegexTokenizer>(options->delim_regex_pattern()->str(), - vocab_buffer.data(), - vocab_buffer.size()); - - int unknown_token_id = 0; - if (!regex_tokenizer->GetUnknownToken(&unknown_token_id)) { - return CreateStatusWithPayload( - absl::StatusCode::kInvalidArgument, - "RegexTokenizer doesn't have <UNKNOWN> token.", - TfLiteSupportStatus::kMetadataInvalidTokenizerError); - } - - int pad_token_id = 0; - if (!regex_tokenizer->GetPadToken(&pad_token_id)) { - return CreateStatusWithPayload( - absl::StatusCode::kInvalidArgument, - "RegexTokenizer doesn't have <PAD> token.", - TfLiteSupportStatus::kMetadataInvalidTokenizerError); - } - return std::move(regex_tokenizer); -} - } // namespace const NLClassifierOptions& NLClassifier::GetOptions() const { @@ -202,58 +122,7 @@ absl::Status NLClassifier::Preprocess( const std::vector<TfLiteTensor*>& input_tensors, const std::string& input) { - TfLiteTensor* input_tensor = FindTensorWithNameOrIndex( - input_tensors, GetMetadataExtractor()->GetInputTensorMetadata(), - struct_options_.input_tensor_name, struct_options_.input_tensor_index); - if (input_tensor == nullptr) { - return CreateStatusWithPayload( - absl::StatusCode::kInvalidArgument, - "No input tensor found from NLClassifierOptions.", - TfLiteSupportStatus::kInputTensorNotFoundError); - } - - if (HasRegexTokenizerMetadata()) { - // |<-------sentence_length-------->| - // input_tensor <START>, t1, t2... <PAD>, <PAD>... - // <START> is optional, t1, t2... will be replaced by <UNKNOWN> if it's not - // found in tokenizer vocab. - TokenizerResult result = tokenizer_->Tokenize(input); - - size_t max_sentence_length = input_tensor->dims->size == 2 - ? input_tensor->dims->data[1] - : input_tensor->dims->data[0]; - - int unknown_token_id = 0; - tokenizer_->GetUnknownToken(&unknown_token_id); - - int pad_token_id = 0; - tokenizer_->GetPadToken(&pad_token_id); - - std::vector<int> input_tokens(max_sentence_length, pad_token_id); - int start_token_id = 0; - size_t input_token_index = 0; - if (tokenizer_->GetStartToken(&start_token_id)) { - input_tokens[0] = start_token_id; - input_token_index = 1; - } - - for (size_t i = 0; (i < result.subwords.size()) && - (input_token_index < max_sentence_length); - ++i, ++input_token_index) { - const std::string& token = result.subwords[i]; - int token_id = 0; - if (tokenizer_->LookupId(token, &token_id)) { - input_tokens[input_token_index] = token_id; - } else { - input_tokens[input_token_index] = unknown_token_id; - } - } - - RETURN_IF_ERROR(PopulateTensor(input_tokens, input_tensor)); - } else { - RETURN_IF_ERROR(PopulateTensor(input, input_tensor)); - } - return absl::OkStatus(); + return preprocessor_->Preprocess(input); } StatusOr<std::vector<Category>> NLClassifier::Postprocess( @@ -328,11 +197,12 @@ absl::Status NLClassifier::Initialize(const NLClassifierOptions& options) { struct_options_ = options; - // input tensor should be type STRING - auto input_tensor = FindTensorWithNameOrIndex( + + int input_index = FindTensorIndex( GetInputTensors(), GetMetadataExtractor()->GetInputTensorMetadata(), options.input_tensor_name, options.input_tensor_index); - if (input_tensor == nullptr) { + + if (input_index < 0 || input_index >= GetInputCount()) { return CreateStatusWithPayload( StatusCode::kInvalidArgument, absl::StrCat("No input tensor found with name ", @@ -340,26 +210,10 @@ options.input_tensor_index), TfLiteSupportStatus::kInputTensorNotFoundError); } - if (HasRegexTokenizerMetadata()) { - if (input_tensor->type != kTfLiteInt32) { - return CreateStatusWithPayload( - StatusCode::kInvalidArgument, - absl::StrCat("Type mismatch for input tensor ", input_tensor->name, - ". Requested INT32, got ", - TfLiteTypeGetName(input_tensor->type), "."), - TfLiteSupportStatus::kInvalidInputTensorTypeError); - } - RETURN_IF_ERROR(SetupRegexTokenizer()); - } else { - if (input_tensor->type != kTfLiteString) { - return CreateStatusWithPayload( - StatusCode::kInvalidArgument, - absl::StrCat("Type mismatch for input tensor ", input_tensor->name, - ". Requested STRING, got ", - TfLiteTypeGetName(input_tensor->type), "."), - TfLiteSupportStatus::kInvalidInputTensorTypeError); - } - } + + // Create preprocessor. + ASSIGN_OR_RETURN(preprocessor_, processor::RegexPreprocessor::Create( + GetTfLiteEngine(), input_index)); // output score tensor should be type // UINT8/INT8/INT16(quantized) or FLOAT32/FLOAT64(dequantized) or BOOL @@ -484,35 +338,6 @@ return std::move(nl_classifier); } -bool NLClassifier::HasRegexTokenizerMetadata() { - const TensorMetadata* input_tensor_metadata = - GetMetadataExtractor()->GetInputTensorMetadata( - kRegexTokenizerInputTensorIndex); - if (input_tensor_metadata == nullptr) { - return false; - } - tflite::support::StatusOr<const tflite::ProcessUnit*> status = - GetMetadataExtractor()->FindFirstProcessUnit( - *input_tensor_metadata, ProcessUnitOptions_RegexTokenizerOptions); - return status.ok() ? status.value() != nullptr : false; -} - -absl::Status NLClassifier::SetupRegexTokenizer() { - ASSIGN_OR_RETURN( - std::unique_ptr<Tokenizer> base_tokenizer, - CreateRegexTokenizerFromProcessUnit( - GetMetadataExtractor() - ->GetInputTensorMetadata(kRegexTokenizerInputTensorIndex) - ->process_units() - ->Get(kRegexTokenizerProcessUnitIndex), - GetMetadataExtractor())); - - tokenizer_ = std::unique_ptr<RegexTokenizer>( - dynamic_cast<RegexTokenizer*>(base_tokenizer.release())); - - return absl::OkStatus(); -} - } // namespace nlclassifier } // namespace text } // namespace task
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h index 331a6e4..30fa2504 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/nlclassifier/nl_classifier.h
@@ -34,8 +34,8 @@ #include "tensorflow_lite_support/cc/port/statusor.h" #include "tensorflow_lite_support/cc/task/core/base_task_api.h" #include "tensorflow_lite_support/cc/task/core/category.h" +#include "tensorflow_lite_support/cc/task/processor/regex_preprocessor.h" #include "tensorflow_lite_support/cc/task/text/proto/nl_classifier_options_proto_inc.h" -#include "tensorflow_lite_support/cc/text/tokenizers/regex_tokenizer.h" namespace tflite { namespace task { @@ -182,36 +182,52 @@ metadata_array, const std::string& name, int index) { + int tensor_index = FindTensorIndex(tensors, metadata_array, name, index); + return tensor_index >= 0 && tensor_index < tensors.size() + ? tensors[tensor_index] + : nullptr; + } + + // Gets the tensor index of the specified tensor name from a vector of tensors + // Return nullptr if no tensor is found by name (metadata tensor name or model + // tensor name). + template <typename TensorType> + static int FindTensorIndex( + const std::vector<TensorType*>& tensors, + const flatbuffers::Vector<flatbuffers::Offset<TensorMetadata>>* + metadata_array, + const std::string& name, + int default_index) { if (metadata_array != nullptr && metadata_array->size() == tensors.size()) { for (size_t i = 0; i < metadata_array->size(); i++) { if (strcmp(name.data(), metadata_array->Get(i)->name()->c_str()) == 0) { - return tensors[i]; + return i; } } } - for (TensorType* tensor : tensors) { + for (int i = 0; i < tensors.size(); i++) { + TensorType* tensor = tensors[i]; if (tensor->name == name) { - return tensor; + return i; } } - return index >= 0 && index < tensors.size() ? tensors[index] : nullptr; + return default_index; } private: - bool HasRegexTokenizerMetadata(); - absl::Status SetupRegexTokenizer(); + std::unique_ptr<tflite::task::processor::RegexPreprocessor> preprocessor_ = + nullptr; std::unique_ptr<tflite::task::text::NLClassifierOptions> proto_options_; - // Deprecated: using the proto_options_ - // (tflite::task::text::NLClassifierOptions). - NLClassifierOptions struct_options_; - // labels vector initialized from output tensor's associated file, if one // exists. std::unique_ptr<std::vector<std::string>> labels_vector_; - std::unique_ptr<tflite::support::text::tokenizer::RegexTokenizer> tokenizer_; + + // Deprecated: using the proto_options_ + // (tflite::task::text::NLClassifierOptions). + NLClassifierOptions struct_options_; }; } // namespace nlclassifier
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/proto/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/proto/BUILD index abc1f24..debdc10b 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/proto/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/proto/BUILD
@@ -102,3 +102,17 @@ "//tensorflow_lite_support/cc/task/vision/proto:embeddings_proto_inc", ], ) + +proto_library( + name = "text_embedder_options_proto", + srcs = ["text_embedder_options.proto"], + deps = [ + "//tensorflow_lite_support/cc/task/core/proto:base_options_proto", + "//tensorflow_lite_support/cc/task/processor/proto:embedding_options_proto", + ], +) + +support_cc_proto_library( + name = "text_embedder_options_cc_proto", + deps = [":text_embedder_options_proto"], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/proto/text_embedder_options.proto b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/proto/text_embedder_options.proto new file mode 100644 index 0000000..ee25417 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/proto/text_embedder_options.proto
@@ -0,0 +1,35 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +syntax = "proto2"; + +package tflite.task.text; + +import "tensorflow_lite_support/cc/task/core/proto/base_options.proto"; +import "tensorflow_lite_support/cc/task/processor/proto/embedding_options.proto"; + +// Options for setting up a TextEmbedder. +// Next Id: 3 +message TextEmbedderOptions { + // Base options for configuring the external model file. + optional tflite.task.core.BaseOptions base_options = 1; + + // Options for each embedding head. If the model contains N heads (embedding + // output tensor), then the len(embedding_options) needs to either + // 0: All output tensors are processed using the *default* EmbeddingOptions. + // 1: All output tensors are processed using the *same* EmbeddingOptions. + // N: Output tensors are processed using the *corresponding* EmbeddingOptions. + repeated tflite.task.processor.EmbeddingOptions embedding_options = 2; +}
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.cc new file mode 100644 index 0000000..e610790 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.cc
@@ -0,0 +1,171 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow_lite_support/cc/task/text/text_embedder.h" + +#include "absl/status/status.h" // from @com_google_absl +#include "tensorflow_lite_support/cc/common.h" +#include "tensorflow_lite_support/cc/port/status_macros.h" +#include "tensorflow_lite_support/cc/port/statusor.h" +#include "tensorflow_lite_support/cc/task/core/task_api_factory.h" +#include "tensorflow_lite_support/cc/task/processor/bert_preprocessor.h" +#include "tensorflow_lite_support/cc/task/processor/regex_preprocessor.h" + +namespace tflite { +namespace task { +namespace text { + +namespace { + +using ::absl::StatusCode; +using ::tflite::support::CreateStatusWithPayload; +using ::tflite::support::TfLiteSupportStatus; +using ::tflite::task::core::TaskAPIFactory; +using ::tflite::task::processor::EmbeddingResult; +using ::tflite::task::processor::FeatureVector; + +absl::Status SanityCheckOptions(const TextEmbedderOptions& options) { + if (!options.has_base_options()) { + return CreateStatusWithPayload(StatusCode::kInvalidArgument, + "Missing mandatory `base_options` field", + TfLiteSupportStatus::kInvalidArgumentError); + } + return absl::OkStatus(); +} + +} // namespace + +/* static */ +tflite::support::StatusOr<double> TextEmbedder::CosineSimilarity( + const FeatureVector& u, + const FeatureVector& v) { + return processor::EmbeddingPostprocessor::CosineSimilarity(u, v); +} + +/* static */ +tflite::support::StatusOr<std::unique_ptr<TextEmbedder>> +TextEmbedder::CreateFromOptions(const TextEmbedderOptions& options, + std::unique_ptr<tflite::OpResolver> resolver) { + RETURN_IF_ERROR(SanityCheckOptions(options)); + // Copy options to ensure the ExternalFile-s outlive the constructed object. + auto options_copy = absl::make_unique<TextEmbedderOptions>(options); + + ASSIGN_OR_RETURN(auto text_embedder, + TaskAPIFactory::CreateFromBaseOptions<TextEmbedder>( + &options_copy->base_options(), std::move(resolver))); + + RETURN_IF_ERROR(text_embedder->Init(std::move(options_copy))); + + return text_embedder; +} + +absl::Status TextEmbedder::Init(std::unique_ptr<TextEmbedderOptions> options) { + // Set options. + options_ = std::move(options); + + // Assuming have only 1 input tensor for RegexPreprocessor and 3 input tensors + // for BertPreprocessor. + + int32_t input_count = GetInputCount(); + if (input_count == 1) { + ASSIGN_OR_RETURN(preprocessor_, processor::RegexPreprocessor::Create( + GetTfLiteEngine(), 0)); + } else if (input_count == 3) { + ASSIGN_OR_RETURN(preprocessor_, processor::BertPreprocessor::Create( + GetTfLiteEngine(), {0, 1, 2})); + } else { + return support::CreateStatusWithPayload( + absl::StatusCode::kInvalidArgument, + absl::StrFormat("Processor can handle 1 tensor or 3 tensors, " + "got: %d tensors.", + input_count)); + } + + // Create postprocessors, assuming that all output tensors are embedding + // outputs. + int post_processors_count = + GetTfLiteEngine()->interpreter()->outputs().size(); + postprocessors_.reserve(post_processors_count); + + for (int i = 0; i < post_processors_count; i++) { + std::unique_ptr<processor::EmbeddingOptions> option = nullptr; + if (options_->embedding_options_size() == 0) { + // Default options. + option = std::make_unique<processor::EmbeddingOptions>(); + } else if (options_->embedding_options_size() == 1) { + // Share the first options. + option = std::make_unique<processor::EmbeddingOptions>( + options_->embedding_options(0)); + } else if (options_->embedding_options_size() == post_processors_count) { + option = std::make_unique<processor::EmbeddingOptions>( + // Use the corresponding options for the tensor. + options_->embedding_options(i)); + } else { + return support::CreateStatusWithPayload( + absl::StatusCode::kInvalidArgument, + "Invalid embedding_options. It should have size of either 0, 1 or " + "number of output tensors.", + support::TfLiteSupportStatus::kInvalidArgumentError); + } + ASSIGN_OR_RETURN(auto processor, + processor::EmbeddingPostprocessor::Create( + GetTfLiteEngine(), {i}, std::move(option))); + postprocessors_.emplace_back(std::move(processor)); + } + + return absl::OkStatus(); +} + +tflite::support::StatusOr<EmbeddingResult> TextEmbedder::Embed( + const std::string& text) { + return InferWithFallback(text); +} + +absl::Status TextEmbedder::Preprocess( + const std::vector<TfLiteTensor*>& input_tensors, + const std::string& input) { + return preprocessor_->Preprocess(input); +} + +// TODO(b/215239176): Creates base Embedder class to share Postprocess / +// GetEmbeddingDimension / GetNumberOfOutputLayers / CosineSimilarity / +// Init (how it creates postprocessors) funcrions between +// Image/Text/AudioEmbedder. +tflite::support::StatusOr<EmbeddingResult> TextEmbedder::Postprocess( + const std::vector<const TfLiteTensor*>& output_tensors, + const std::string& input) { + EmbeddingResult result; + for (int i = 0; i < postprocessors_.size(); ++i) { + RETURN_IF_ERROR( + postprocessors_.at(i)->Postprocess(result.add_embeddings())); + } + + return result; +} + +int TextEmbedder::GetEmbeddingDimension(int output_index) const { + if (output_index < 0 || output_index >= postprocessors_.size()) { + return -1; + } + return postprocessors_.at(output_index)->GetEmbeddingDimension(); +} + +int TextEmbedder::GetNumberOfOutputLayers() const { + return postprocessors_.size(); +} + +} // namespace text +} // namespace task +} // namespace tflite
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.h new file mode 100644 index 0000000..b76b74ea --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/text_embedder.h
@@ -0,0 +1,110 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_SUPPORT_CC_TASK_TEXT_TEXT_EMBEDDER_H_ +#define TENSORFLOW_LITE_SUPPORT_CC_TASK_TEXT_TEXT_EMBEDDER_H_ + +#include <string> +#include <vector> + +#include "absl/status/status.h" // from @com_google_absl +#include "tensorflow/lite/core/api/op_resolver.h" +#include "tensorflow/lite/core/shims/cc/kernels/register.h" +#include "tensorflow_lite_support/cc/port/statusor.h" +#include "tensorflow_lite_support/cc/task/core/base_task_api.h" +#include "tensorflow_lite_support/cc/task/processor/embedding_postprocessor.h" +#include "tensorflow_lite_support/cc/task/processor/proto/embedding.pb.h" +#include "tensorflow_lite_support/cc/task/processor/proto/embedding_options.pb.h" +#include "tensorflow_lite_support/cc/task/processor/text_preprocessor.h" +#include "tensorflow_lite_support/cc/task/text/proto/text_embedder_options.pb.h" + +namespace tflite { +namespace task { +namespace text { + +// Performs dense feature vector extraction on text. +// +// The API expects a Regex/Bert based TFLite model with metadata populated. +// The metadata should contain the following information: +// 1. For Bert based TFLite model. +// - input_process_units for Wordpiece/Sentencepiece Tokenizer +// - 3 input tensors with names "ids", "mask" and "segment_ids". +// 2. For Regex based TFLite model. +// - input_process_units for RegexTokenizer Tokenizer +// - 1 input tensor. +class TextEmbedder + : public core::BaseTaskApi<processor::EmbeddingResult, const std::string&> { + public: + // Use base class constructor. + using BaseTaskApi::BaseTaskApi; + + // Creates a TextEmbedder from the provided options. A non-default + // OpResolver can be specified in order to support custom Ops or specify a + // subset of built-in Ops. + static tflite::support::StatusOr<std::unique_ptr<TextEmbedder>> + CreateFromOptions( + const TextEmbedderOptions& options, + std::unique_ptr<tflite::OpResolver> resolver = + absl::make_unique<tflite_shims::ops::builtin::BuiltinOpResolver>()); + + // Performs actual feature vector extraction on the provided raw text. + tflite::support::StatusOr<processor::EmbeddingResult> Embed( + const std::string& text); + + // Returns the dimensionality of the embedding output by the output_index'th + // output layer. Returns -1 if `output_index` is out of bounds. + int GetEmbeddingDimension(int output_index) const; + + // Returns the number of output layers of the model. + int GetNumberOfOutputLayers() const; + + // Utility function to compute cosine similarity [1] between two feature + // vectors. May return an InvalidArgumentError if e.g. the feature vectors are + // of different types (quantized vs. float), have different sizes, or have a + // an L2-norm of 0. + // + // [1]: https://en.wikipedia.org/wiki/Cosine_similarity + static tflite::support::StatusOr<double> CosineSimilarity( + const processor::FeatureVector& u, + const processor::FeatureVector& v); + + protected: + // The options used to build this TextEmbedder. + std::unique_ptr<TextEmbedderOptions> options_; + + // Passes through the input raw text into model's input tensor. + absl::Status Preprocess(const std::vector<TfLiteTensor*>& input_tensors, + const std::string& input) override; + + // Post-processing to transform the raw model outputs into embedding results. + tflite::support::StatusOr<processor::EmbeddingResult> Postprocess( + const std::vector<const TfLiteTensor*>& output_tensors, + const std::string& input) override; + + // Initializes the TextEmbedder. + absl::Status Init(std::unique_ptr<TextEmbedderOptions> options); + + private: + std::unique_ptr<tflite::task::processor::TextPreprocessor> preprocessor_ = + nullptr; + std::vector<std::unique_ptr<processor::EmbeddingPostprocessor>> + postprocessors_; +}; + +} // namespace text +} // namespace task +} // namespace tflite + +#endif // TENSORFLOW_LITE_SUPPORT_CC_TASK_TEXT_TEXT_EMBEDDER_H_
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.cc index 2937a175..18a73b0a 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.cc
@@ -15,6 +15,7 @@ #include "tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h" #include <algorithm> +#include <cstdint> #include <memory> #include <string> #include <utility> @@ -30,18 +31,8 @@ #include "tensorflow_lite_support/cc/task/text/proto/retrieval.pb.h" namespace tflite { -namespace ops { -namespace custom { -TfLiteRegistration* Register_SENTENCEPIECE_TOKENIZER(); -TfLiteRegistration* Register_RAGGED_TENSOR_TO_TENSOR(); -} // namespace custom -} // namespace ops -} // namespace tflite - -namespace tflite { namespace task { namespace text { -namespace retrieval { using ::absl::Status; using ::absl::StatusCode; @@ -49,18 +40,27 @@ using internal::QAOutput; using ::tflite::support::StatusOr; using ::tflite::support::TfLiteSupportStatus; -using ::tflite::task::core::FindTensorByName; +using ::tflite::task::core::FindTensorIndexByName; using ::tflite::task::core::PopulateTensor; using ::tflite::task::core::PopulateVectorToRepeated; using ::tflite::task::core::TaskAPIFactory; using FeatureVector = UniversalSentenceEncoderQA::FeatureVector; namespace { -constexpr char kQueryTextTensorName[] = "inp_text"; -constexpr char kResponseTextTensorName[] = "res_text"; -constexpr char kResponseContextTensorName[] = "res_context"; -constexpr char kQueryEncodingTensorName[] = "query_encoding"; -constexpr char kResponseEncodingTensorName[] = "response_encoding"; +constexpr char kQueryTextMetadataName[] = "inp_text"; +constexpr char kResponseContextMetadataName[] = "res_context"; +constexpr char kResponseTextMetadataName[] = "res_text"; +constexpr char kQueryEncodingMetadataName[] = "query_encoding"; +constexpr char kResponseEncodingMetadataName[] = "response_encoding"; + +constexpr char kQueryTextTensorName[] = "ParseExample/ParseExampleV2:1"; +constexpr char kResponseContextTensorName[] = "ParseExample/ParseExampleV2:2"; +constexpr char kResponseTextTensorName[] = "ParseExample/ParseExampleV2:3"; +constexpr char kQueryEncodingTensorName[] = "Final/EncodeQuery/mul"; +constexpr char kResponseEncodingTensorName[] = "Final/EncodeResult/mul"; + +constexpr int kDefaultInputTensorIndices[3] = {0, 1, 2}; +constexpr int kDefaultOutputTensorIndices[2] = {0, 1}; // Sanity check for options to ensure required fields. absl::Status SanityCheckOptions(const RetrievalOptions& options) { @@ -107,20 +107,6 @@ }; } // namespace internal -// Creates custom op resolver for USE QA task. -std::unique_ptr<tflite_shims::ops::builtin::BuiltinOpResolver> -CreateQACustomOpResolver() { - auto resolver = - absl::make_unique<tflite_shims::ops::builtin::BuiltinOpResolver>(); - resolver->AddCustom( - "TFSentencepieceTokenizeOp", - ::tflite::ops::custom::Register_SENTENCEPIECE_TOKENIZER()); - resolver->AddCustom( - "RaggedTensorToTensor", - ::tflite::ops::custom::Register_RAGGED_TENSOR_TO_TENSOR()); - return resolver; -} - constexpr int UniversalSentenceEncoderQA::kFinalEmbeddingSize; StatusOr<RetrievalOutput> UniversalSentenceEncoderQA::Retrieve( @@ -246,28 +232,12 @@ Status UniversalSentenceEncoderQA::Preprocess( const std::vector<TfLiteTensor*>& input_tensors, const QAInput& input) { - auto* input_tensor_metadatas = - GetMetadataExtractor()->GetInputTensorMetadata(); - TfLiteTensor* query_text_tensor = - input_tensor_metadatas - ? FindTensorByName(input_tensors, input_tensor_metadatas, - kQueryTextTensorName) - : input_tensors[0]; - TfLiteTensor* response_text_tensor = - input_tensor_metadatas - ? FindTensorByName(input_tensors, input_tensor_metadatas, - kResponseTextTensorName) - : input_tensors[2]; - TfLiteTensor* response_context_tensor = - input_tensor_metadatas - ? FindTensorByName(input_tensors, input_tensor_metadatas, - kResponseContextTensorName) - : input_tensors[1]; - - RETURN_IF_ERROR(PopulateTensor(input.query_text, query_text_tensor)); - RETURN_IF_ERROR(PopulateTensor(input.response_text, response_text_tensor)); RETURN_IF_ERROR( - PopulateTensor(input.response_context, response_context_tensor)); + PopulateTensor(input.query_text, input_tensors[input_indices_[0]])); + RETURN_IF_ERROR( + PopulateTensor(input.response_context, input_tensors[input_indices_[1]])); + RETURN_IF_ERROR( + PopulateTensor(input.response_text, input_tensors[input_indices_[2]])); return absl::OkStatus(); } @@ -275,23 +245,9 @@ StatusOr<QAOutput> UniversalSentenceEncoderQA::Postprocess( const std::vector<const TfLiteTensor*>& output_tensors, const QAInput& /*input*/) { - auto* output_tensor_metadatas = - GetMetadataExtractor()->GetOutputTensorMetadata(); - - const TfLiteTensor* output_query_encoding_tensor = - output_tensor_metadatas - ? FindTensorByName(output_tensors, output_tensor_metadatas, - kQueryEncodingTensorName) - : output_tensors[0]; - const TfLiteTensor* output_response_encoding_tensor = - output_tensor_metadatas - ? FindTensorByName(output_tensors, output_tensor_metadatas, - kResponseEncodingTensorName) - : output_tensors[1]; - QAOutput output; - output.query_encoding = output_query_encoding_tensor; - output.response_encoding = output_response_encoding_tensor; + output.query_encoding = output_tensors[output_indices_[0]]; + output.response_encoding = output_tensors[output_indices_[1]]; return output; } @@ -300,12 +256,72 @@ absl::string_view response_text, absl::string_view response_context) { QAInput input; - input.query_text = query_text; - input.response_text = response_text; - input.response_context = response_context; + input.query_text = std::string(query_text); + input.response_text = std::string(response_text); + input.response_context = std::string(response_context); return Infer(input).value(); } +absl::Status UniversalSentenceEncoderQA::Init( + std::unique_ptr<RetrievalOptions> options) { + options_ = std::move(options); + + auto input_tensors = GetInputTensors(); + if (input_tensors.size() < 3) { + return CreateStatusWithPayload( + StatusCode::kInvalidArgument, + "The number of input tensors should be at least 3, including query text" + " input, response context input, response text input.", + TfLiteSupportStatus::kInvalidArgumentError); + } + + auto* input_tensor_metadatas = + GetMetadataExtractor()->GetInputTensorMetadata(); + input_indices_ = { + FindTensorIndexByName(input_tensors, input_tensor_metadatas, + kQueryTextMetadataName, kQueryTextTensorName), + FindTensorIndexByName(input_tensors, input_tensor_metadatas, + kResponseContextMetadataName, + kResponseContextTensorName), + FindTensorIndexByName(input_tensors, input_tensor_metadatas, + kResponseTextMetadataName, + kResponseTextTensorName)}; + if (std::find(input_indices_.begin(), input_indices_.end(), -1) != + input_indices_.end()) { + // Use the default index if any input tensor is not found. + input_indices_ = std::vector<int>(std::begin(kDefaultInputTensorIndices), + std::end(kDefaultInputTensorIndices)); + } + + auto output_tensors = GetOutputTensors(); + if (output_tensors.size() < 2) { + return CreateStatusWithPayload( + StatusCode::kInvalidArgument, + "The number of output tensors should be at least 2, including query " + "encoding output, response encoding output.", + TfLiteSupportStatus::kInvalidArgumentError); + } + + auto* output_tensor_metadatas = + GetMetadataExtractor()->GetOutputTensorMetadata(); + output_indices_ = { + FindTensorIndexByName(output_tensors, output_tensor_metadatas, + kQueryEncodingMetadataName, + kQueryEncodingTensorName), + FindTensorIndexByName(output_tensors, output_tensor_metadatas, + kResponseEncodingMetadataName, + kResponseEncodingTensorName)}; + + if (std::find(output_indices_.begin(), output_indices_.end(), -1) != + output_indices_.end()) { + // Use the default index if any output tensor is not found. + output_indices_ = std::vector<int>(std::begin(kDefaultOutputTensorIndices), + std::end(kDefaultOutputTensorIndices)); + } + + return absl::OkStatus(); +} // namespace retrieval + StatusOr<std::unique_ptr<UniversalSentenceEncoderQA>> UniversalSentenceEncoderQA::CreateFromOption( const RetrievalOptions& options, @@ -320,11 +336,11 @@ auto encoder, TaskAPIFactory::CreateFromBaseOptions<UniversalSentenceEncoderQA>( &options_copy->base_options(), std::move(resolver))); - encoder->proto_options_ = std::move(options_copy); - return std::move(encoder); + + RETURN_IF_ERROR(encoder->Init(std::move(options_copy))); + return encoder; } -} // namespace retrieval } // namespace text } // namespace task } // namespace tflite
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h index 0269033..8a05998 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h
@@ -12,8 +12,8 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#ifndef THIRD_PARTY_TENSORFLOW_LITE_SUPPORT_CC_TASK_TEXT_UNIVERSAL_SENTENCE_ENCODER_QA_H_ -#define THIRD_PARTY_TENSORFLOW_LITE_SUPPORT_CC_TASK_TEXT_UNIVERSAL_SENTENCE_ENCODER_QA_H_ +#ifndef TENSORFLOW_LITE_SUPPORT_CC_TASK_TEXT_UNIVERSAL_SENTENCE_ENCODER_QA_H_ +#define TENSORFLOW_LITE_SUPPORT_CC_TASK_TEXT_UNIVERSAL_SENTENCE_ENCODER_QA_H_ #include <string> #include <utility> @@ -32,7 +32,6 @@ namespace tflite { namespace task { namespace text { -namespace retrieval { // QAInput and QAOutput for UniversalSentenceEncoderQA internally. namespace internal { @@ -40,12 +39,27 @@ struct QAOutput; } // namespace internal -// Creates custom op resolver for USE QA task. -std::unique_ptr<tflite_shims::ops::builtin::BuiltinOpResolver> -CreateQACustomOpResolver(); - // Universal Sentence Encoder (USE) Question Answerer. The model uses USE as the // backbone and answers a question. +// +// The API expects an USE QA model with the following input and output tensor +// names: +// Metadata tensor name | Model tensor name +// Inputs tensors: | +// - Query text "inp_text" | "ParseExample/ParseExampleV2:1" +// - Response text: "res_text" | "ParseExample/ParseExampleV2:2" +// - Response context "res_context" | "ParseExample/ParseExampleV2:3" +// Output tensors: +// - Query encoding "query_encoding" | "Final/EncodeQuery/mul" +// - Response encoding "response_encoding"| "Final/EncodeResult/mul" +// +// Tensors will be matched by first checking the metadata tesnor name and then +// the Model tensor name. If no matching tensor name is found, the first three +// input tensors will be used for query text, response text, response context, +// respectively; the first two output tensors will be used for query_encoding +// and response encoding, respectively. Other input or output tensors will be +// ignored by `UniversalSentenceEncoderQA`. + class UniversalSentenceEncoderQA : public core::BaseTaskApi<internal::QAOutput, const internal::QAInput&> { public: @@ -56,9 +70,10 @@ static constexpr int kFinalEmbeddingSize = 100; static tflite::support::StatusOr<std::unique_ptr<UniversalSentenceEncoderQA>> - CreateFromOption(const tflite::task::text::RetrievalOptions& options, - std::unique_ptr<tflite::OpResolver> resolver = - CreateQACustomOpResolver()); + CreateFromOption( + const tflite::task::text::RetrievalOptions& options, + std::unique_ptr<tflite::OpResolver> resolver = + absl::make_unique<tflite_shims::ops::builtin::BuiltinOpResolver>()); // Retrieves output from the input by running TFLite engine. // Returns an error, if either query_text or responses is empty. @@ -85,6 +100,8 @@ static std::vector<size_t> Top(const RetrievalOutput& output, size_t k = 0); private: + absl::Status Init(std::unique_ptr<RetrievalOptions> options); + absl::Status Preprocess(const std::vector<TfLiteTensor*>& input_tensors, const internal::QAInput& input) override; @@ -96,12 +113,19 @@ absl::string_view response_text, absl::string_view response_context); - std::unique_ptr<tflite::task::text::RetrievalOptions> proto_options_; + std::unique_ptr<tflite::task::text::RetrievalOptions> options_; + + // The input tensor indices corresponding to the query text tensor, the + // response context tensor, and the response text tensor, respectively. + std::vector<int> input_indices_; + + // The output tensor indices corresponding to the query encoding tensor and + // the response encoding tensor, respectively. + std::vector<int> output_indices_; }; -} // namespace retrieval } // namespace text } // namespace task } // namespace tflite -#endif // THIRD_PARTY_TENSORFLOW_LITE_SUPPORT_CC_TASK_TEXT_UNIVERSAL_SENTENCE_ENCODER_QA_H_ +#endif // TENSORFLOW_LITE_SUPPORT_CC_TASK_TEXT_UNIVERSAL_SENTENCE_ENCODER_QA_H_
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/image_segmenter.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/image_segmenter.cc index 20a34a9..1cf9a54 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/image_segmenter.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/image_segmenter.cc
@@ -20,7 +20,7 @@ #include "absl/memory/memory.h" // from @com_google_absl #include "absl/strings/str_format.h" // from @com_google_absl #include "absl/strings/string_view.h" // from @com_google_absl -#include "flatbuffers/flatbuffers.h" // from @flatbuffers +#include "flatbuffers/flatbuffers.h" // from @flatbuffers #include "tensorflow/lite/c/common.h" #include "tensorflow_lite_support/cc/common.h" #include "tensorflow_lite_support/cc/port/integral_types.h" @@ -124,7 +124,7 @@ ModelMetadataExtractor::FindFirstAssociatedFileName( tensor_metadata, tflite::AssociatedFileType_TENSOR_AXIS_LABELS, locale); - absl::string_view display_names_file = nullptr; + absl::string_view display_names_file = {}; if (!display_names_filename.empty()) { ASSIGN_OR_RETURN(display_names_file, metadata_extractor.GetAssociatedFile( display_names_filename));
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/object_detector.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/object_detector.cc index 3eb5126..ade2de7 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/object_detector.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/object_detector.cc
@@ -57,7 +57,7 @@ using ::tflite::support::StatusOr; using ::tflite::support::TfLiteSupportStatus; using ::tflite::task::core::AssertAndReturnTypedTensor; -using ::tflite::task::core::FindIndexByMetadataTensorName; +using ::tflite::task::core::FindTensorIndexByMetadataName; using ::tflite::task::core::TaskAPIFactory; using ::tflite::task::core::TfLiteEngine; @@ -182,10 +182,10 @@ const flatbuffers::Vector<flatbuffers::Offset<TensorMetadata>>* tensor_metadatas) { std::vector<int> output_indices = { - FindIndexByMetadataTensorName(tensor_metadatas, kLocationTensorName), - FindIndexByMetadataTensorName(tensor_metadatas, kCategoryTensorName), - FindIndexByMetadataTensorName(tensor_metadatas, kScoreTensorName), - FindIndexByMetadataTensorName(tensor_metadatas, + FindTensorIndexByMetadataName(tensor_metadatas, kLocationTensorName), + FindTensorIndexByMetadataName(tensor_metadatas, kCategoryTensorName), + FindTensorIndexByMetadataName(tensor_metadatas, kScoreTensorName), + FindTensorIndexByMetadataName(tensor_metadatas, kNumberOfDetectionsTensorName)}; for (int i = 0; i < 4; i++) {
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/BUILD index 16ea0cd..d845d16 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/BUILD
@@ -1,3 +1,5 @@ +load("//tensorflow_lite_support/cc/port:build_defs.bzl", "support_py_proto_library") + package( default_visibility = [ "//visibility:public", @@ -19,6 +21,13 @@ ], ) +support_py_proto_library( + name = "bounding_box_py_pb2", + srcs = ["bounding_box.proto"], + api_version = 2, + proto_deps = [":bounding_box_proto"], +) + cc_library( name = "bounding_box_proto_inc", hdrs = ["bounding_box_proto_inc.h"], @@ -37,6 +46,13 @@ ], ) +support_py_proto_library( + name = "class_py_pb2", + srcs = ["class.proto"], + api_version = 2, + proto_deps = [":class_proto"], +) + cc_library( name = "class_proto_inc", hdrs = ["class_proto_inc.h"], @@ -117,6 +133,17 @@ ], ) +support_py_proto_library( + name = "image_classifier_options_py_pb2", + srcs = ["image_classifier_options.proto"], + api_version = 2, + proto_deps = [":image_classifier_options_proto"], + py_proto_deps = [ + "@org_tensorflow//tensorflow/lite/experimental/acceleration/configuration:configuration_proto_external_py", + "//tensorflow_lite_support/cc/task/core/proto:external_file_py_pb2", + ], +) + cc_library( name = "image_classifier_options_proto_inc", hdrs = ["image_classifier_options_proto_inc.h"], @@ -142,6 +169,13 @@ ], ) +support_py_proto_library( + name = "classifications_py_pb2", + srcs = ["classifications.proto"], + api_version = 2, + proto_deps = [":classifications_proto"], +) + cc_library( name = "classifications_proto_inc", hdrs = ["classifications_proto_inc.h"], @@ -216,6 +250,17 @@ ], ) +support_py_proto_library( + name = "image_embedder_options_py_pb2", + srcs = ["image_embedder_options.proto"], + api_version = 2, + proto_deps = [":image_embedder_options_proto"], + py_proto_deps = [ + "@org_tensorflow//tensorflow/lite/experimental/acceleration/configuration:configuration_proto_external_py", + "//tensorflow_lite_support/cc/task/core/proto:external_file_py_pb2", + ], +) + cc_library( name = "image_embedder_options_proto_inc", hdrs = ["image_embedder_options_proto_inc.h"], @@ -237,6 +282,13 @@ ], ) +support_py_proto_library( + name = "embeddings_py_pb2", + srcs = ["embeddings.proto"], + api_version = 2, + proto_deps = [":embeddings_proto"], +) + cc_library( name = "embeddings_proto_inc", hdrs = ["embeddings_proto_inc.h"],
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/segmentations.proto b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/segmentations.proto index f6df558..259bee81 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/segmentations.proto +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/task/vision/proto/segmentations.proto
@@ -31,13 +31,17 @@ // pixel, the value indicates the prediction confidence usually in the [0, 1] // range where higher values represent a stronger confidence. Ultimately this // is model specific, and other range of values might be used. - message ConfidenceMask { repeated float value = 1 [packed = true]; } + message ConfidenceMask { + repeated float value = 1 [packed = true]; + } // List of confidence masks with respect to the model output depth (this depth // represents how many classes are supported). Note: some models have a single // class (e.g. a sky segmentation model) which turns into a single confidence // mask in this list. - message ConfidenceMasks { repeated ConfidenceMask confidence_mask = 1; } + message ConfidenceMasks { + repeated ConfidenceMask confidence_mask = 1; + } // IMPORTANT: segmentation masks are not direcly suited for display, in // particular:
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/text/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/text/BUILD index 57f26345..858d7e73 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/text/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/text/BUILD
@@ -46,3 +46,22 @@ "@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util", ], ) + +cc_test( + name = "text_embedder_test", + srcs = ["text_embedder_test.cc"], + data = [ + "//tensorflow_lite_support/cc/test/testdata/task/text:mobilebert_embedding_with_metadata", + "//tensorflow_lite_support/cc/test/testdata/task/text:regex_embedding_with_metadata", + ], + deps = [ + "//tensorflow_lite_support/cc/port:gtest_main", + "//tensorflow_lite_support/cc/task/core/proto:base_options_proto_inc", + "//tensorflow_lite_support/cc/task/processor/proto:embedding_options_cc_proto", + "//tensorflow_lite_support/cc/task/text:text_embedder", + "//tensorflow_lite_support/cc/test:test_utils", + "@com_google_absl//absl/status", + "@com_google_absl//absl/strings", + "@org_tensorflow//tensorflow/lite/core/shims:cc_shims_test_util", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/text/text_embedder_test.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/text/text_embedder_test.cc new file mode 100644 index 0000000..6bf72b83 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/text/text_embedder_test.cc
@@ -0,0 +1,179 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#include "tensorflow_lite_support/cc/task/text/text_embedder.h" + +#include <iostream> + +#include "absl/status/status.h" // from @com_google_absl +#include "absl/strings/string_view.h" // from @com_google_absl +#include "tensorflow/lite/core/shims/cc/shims_test_util.h" +#include "tensorflow_lite_support/cc/port/gmock.h" +#include "tensorflow_lite_support/cc/port/gtest.h" +#include "tensorflow_lite_support/cc/port/status_matchers.h" +#include "tensorflow_lite_support/cc/task/core/proto/base_options_proto_inc.h" +#include "tensorflow_lite_support/cc/task/processor/proto/embedding_options.pb.h" +#include "tensorflow_lite_support/cc/test/test_utils.h" + +namespace tflite { +namespace task { +namespace text { +namespace { + +using ::tflite::support::StatusOr; + +constexpr char kTestDataDirectory[] = + "/tensorflow_lite_support/cc/test/testdata/task/text/"; +constexpr char kMobileBert[] = "mobilebert_embedding_with_metadata.tflite"; +// Embedding model with regex preprocessing and one embedding output. +constexpr char kRegexOneEmbeddingModel[] = + "regex_one_embedding_with_metadata.tflite"; +// Embedding model with regex preprocessing and two embedding outputs. +constexpr char kRegexTwoEmbeddingsModel[] = + "regex_two_embeddings_with_metadata.tflite"; +constexpr int kNumberOfOutputLayers = 1; +constexpr float kValueDiffTolerance = 1e-4; +// Tolerancy for cosine similarity evaluation. +constexpr double kSimilarityTolerancy = 1e-6; + +class CreateFromOptionsTest : public tflite_shims::testing::Test {}; + +TextEmbedderOptions GetBasicOptions(absl::string_view model_name) { + TextEmbedderOptions options; + options.mutable_base_options()->mutable_model_file()->set_file_name( + JoinPath("./" /*test src dir*/, kTestDataDirectory, model_name)); + return options; +} + +TEST_F(CreateFromOptionsTest, SucceedsWithMobileBertWithoutEmbeddingOptions) { + // Mobilebert model. + TextEmbedderOptions options0 = GetBasicOptions(kMobileBert); + // No Embedding options means all head get a default option. + SUPPORT_ASSERT_OK(TextEmbedder::CreateFromOptions(options0)); + + // Regex model with one embedding output. + TextEmbedderOptions options1 = GetBasicOptions(kRegexOneEmbeddingModel); + // No Embedding options means all head get a default option. + SUPPORT_ASSERT_OK(TextEmbedder::CreateFromOptions(options1)); + + // Regex model with two embedding output. + TextEmbedderOptions options2 = GetBasicOptions(kRegexTwoEmbeddingsModel); + // No Embedding options means all head get a default option. + SUPPORT_ASSERT_OK(TextEmbedder::CreateFromOptions(options2)); +} + +TEST_F(CreateFromOptionsTest, SucceedsWithSingleEmbeddingOptions) { + // Mobilebert model. + TextEmbedderOptions options = GetBasicOptions(kMobileBert); + // Single embedding options means all head get the same option. + options.add_embedding_options(); + SUPPORT_ASSERT_OK(TextEmbedder::CreateFromOptions(options)); + + // Regex model with one embedding output. + TextEmbedderOptions options1 = GetBasicOptions(kRegexOneEmbeddingModel); + // Single embedding options means all head get the same option. + options1.add_embedding_options(); + SUPPORT_ASSERT_OK(TextEmbedder::CreateFromOptions(options1)); + + // Regex model with two embedding output. + TextEmbedderOptions options2 = GetBasicOptions(kRegexTwoEmbeddingsModel); + // Single embedding options means all head get the same option. + options2.add_embedding_options(); + SUPPORT_ASSERT_OK(TextEmbedder::CreateFromOptions(options2)); +} + +TEST_F(CreateFromOptionsTest, FailsWithIncorrectNumberOfHeadOptions) { + TextEmbedderOptions options = GetBasicOptions(kMobileBert); + // The model has only 1 head, so it can't take two embedding options. + options.add_embedding_options(); + options.add_embedding_options(); + + StatusOr<std::unique_ptr<TextEmbedder>> text_embedder_or = + TextEmbedder::CreateFromOptions(options); + EXPECT_EQ(text_embedder_or.status().code(), + absl::StatusCode::kInvalidArgument); + EXPECT_THAT(text_embedder_or.status().message(), + testing::HasSubstr("Invalid embedding_options")); +} + +TEST_F(CreateFromOptionsTest, FailsWithMissingModel) { + TextEmbedderOptions options; + + StatusOr<std::unique_ptr<TextEmbedder>> text_embedder_or = + TextEmbedder::CreateFromOptions(options); + + EXPECT_EQ(text_embedder_or.status().code(), + absl::StatusCode::kInvalidArgument); + EXPECT_THAT( + text_embedder_or.status().GetPayload(support::kTfLiteSupportPayload), + testing::Optional(absl::Cord( + absl::StrCat(support::TfLiteSupportStatus::kInvalidArgumentError)))); +} + +TEST(EmbedTest, SucceedsWithRegexModel) { + TextEmbedderOptions options = GetBasicOptions(kRegexOneEmbeddingModel); + // No Embedding options means all head get a default option. + SUPPORT_ASSERT_OK_AND_ASSIGN(std::unique_ptr<TextEmbedder> text_embedder, + TextEmbedder::CreateFromOptions(options)); + + SUPPORT_ASSERT_OK_AND_ASSIGN( + auto result0, + text_embedder->Embed("it's a charming and often affecting journey")); + EXPECT_EQ(result0.embeddings_size(), 1); + EXPECT_EQ(result0.embeddings(0).feature_vector().value_float_size(), 16); + + EXPECT_NEAR(result0.embeddings(0).feature_vector().value_float(0), 0.0309356f, + kValueDiffTolerance); + + SUPPORT_ASSERT_OK_AND_ASSIGN( + auto result1, text_embedder->Embed("what a great and fantastic trip")); + EXPECT_EQ(result1.embeddings_size(), 1); + EXPECT_EQ(result1.embeddings(0).feature_vector().value_float_size(), 16); + + EXPECT_NEAR(result1.embeddings(0).feature_vector().value_float(0), 0.0312863f, + kValueDiffTolerance); + + // Check cosine similarity. + SUPPORT_ASSERT_OK_AND_ASSIGN( + double similarity, + TextEmbedder::CosineSimilarity(result0.embeddings(0).feature_vector(), + result1.embeddings(0).feature_vector())); + double expected_similarity = 0.999937; + EXPECT_NEAR(similarity, expected_similarity, kSimilarityTolerancy); +} + +TEST(GetEmbeddingDimension, Succeeds) { + // Create embedder. + TextEmbedderOptions options = GetBasicOptions(kMobileBert); + SUPPORT_ASSERT_OK_AND_ASSIGN(std::unique_ptr<TextEmbedder> text_embedder, + TextEmbedder::CreateFromOptions(options)); + + EXPECT_EQ(text_embedder->GetEmbeddingDimension(0), 512); + EXPECT_EQ(text_embedder->GetEmbeddingDimension(1), -1); + EXPECT_EQ(text_embedder->GetEmbeddingDimension(-1), -1); +} + +TEST(GetNumberOfOutputLayers, Succeeds) { + TextEmbedderOptions options = GetBasicOptions(kMobileBert); + // No Embedding options means all head get a default option. + SUPPORT_ASSERT_OK_AND_ASSIGN(std::unique_ptr<TextEmbedder> text_embedder, + TextEmbedder::CreateFromOptions(options)); + EXPECT_EQ(text_embedder->GetNumberOfOutputLayers(), kNumberOfOutputLayers); +} + +} // namespace +} // namespace text +} // namespace task +} // namespace tflite
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/BUILD index 24a4b9108..73a9a02d 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/BUILD
@@ -41,6 +41,7 @@ "@com_google_absl//absl/strings:cord", "@org_tensorflow//tensorflow/lite:framework", "@org_tensorflow//tensorflow/lite/c:common", + "@org_tensorflow//tensorflow/lite/experimental/acceleration/mini_benchmark:mini_benchmark_implementation", # Activating mini-benchmark "@org_tensorflow//tensorflow/lite/kernels:builtin_ops", ], )
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/image_classifier_test.cc b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/image_classifier_test.cc index ae4e48c..c40836e 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/image_classifier_test.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/task/vision/image_classifier_test.cc
@@ -423,6 +423,74 @@ )pb")); } +// Configure the ImageClassifier to use the mini-benchmark to decide if we +// should use the XNNPack Delegate with the given number of threads. +void ConfigureXnnPackMiniBenchmark(int num_threads, + ImageClassifierOptions& options) { + auto* mutable_mini_benchmark_settings = + options.mutable_base_options() + ->mutable_compute_settings() + ->mutable_settings_to_test_locally(); + auto* setting_to_benchmark = + mutable_mini_benchmark_settings->add_settings_to_test(); + setting_to_benchmark->set_delegate(tflite::proto::Delegate::XNNPACK); + setting_to_benchmark->mutable_xnnpack_settings()->set_num_threads( + num_threads); + + // Configuring mini-benchmark storage paths + mutable_mini_benchmark_settings->mutable_storage_paths() + ->set_storage_file_path( + JoinPath(testing::TempDir(), "mini_benchmark_storage")); + mutable_mini_benchmark_settings->mutable_storage_paths() + ->set_data_directory_path(testing::TempDir()); +} + +TEST(ClassifyTest, SucceedsWithMiniBenchmark) { + SUPPORT_ASSERT_OK_AND_ASSIGN(ImageData rgb_image, LoadImage("burger.jpg")); + std::unique_ptr<FrameBuffer> frame_buffer = CreateFromRgbRawBuffer( + rgb_image.pixel_data, + FrameBuffer::Dimension{rgb_image.width, rgb_image.height}); + + auto file_name = JoinPath("./" /*test src dir*/, kTestDataDirectory, + kMobileNetFloatWithMetadata); + + ImageClassifierOptions options; + options.set_max_results(3); + options.mutable_base_options()->mutable_model_file()->set_file_name( + file_name); + + ConfigureXnnPackMiniBenchmark(/*num_threads=*/2, options); + + SUPPORT_ASSERT_OK_AND_ASSIGN( + std::unique_ptr<ImageClassifier> image_classifier, + ImageClassifier::CreateFromOptions(options)); + + StatusOr<ClassificationResult> result_or = + image_classifier->Classify(*frame_buffer); + ImageDataFree(&rgb_image); + SUPPORT_ASSERT_OK(result_or); + + const ClassificationResult& result = result_or.value(); + ExpectApproximatelyEqual( + result, + ParseTextProtoOrDie<ClassificationResult>( + R"pb(classifications { + classes { + index: 934 + score: 0.7399742 + class_name: "cheeseburger" + } + classes { + index: 925 + score: 0.026928535 + class_name: "guacamole" + } + classes { index: 932 score: 0.025737215 class_name: "bagel" } + head_index: 0 + } + )pb")); +} + TEST(ClassifyTest, GetInputCountSucceeds) { ImageClassifierOptions options; options.mutable_base_options()->mutable_model_file()->set_file_name(JoinPath(
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/testdata/task/text/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/testdata/task/text/BUILD index 72a88c2..487f606 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/testdata/task/text/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/testdata/task/text/BUILD
@@ -56,6 +56,16 @@ data = [":universal_sentence_encoder_qa_with_metadata"], ) +tflite_model(name = "mobilebert_embedding_with_metadata") + +filegroup( + name = "regex_embedding_with_metadata", + srcs = [ + "regex_one_embedding_with_metadata.tflite", + "regex_two_embeddings_with_metadata.tflite", + ], +) + tflite_model(name = "bert_nl_classifier") tflite_model(name = "albert")
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/testdata/task/text/regex_one_embedding_with_metadata.tflite b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/testdata/task/text/regex_one_embedding_with_metadata.tflite new file mode 100644 index 0000000..e77cbea --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/testdata/task/text/regex_one_embedding_with_metadata.tflite Binary files differ
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/test/testdata/task/text/regex_two_embeddings_with_metadata.tflite b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/testdata/task/text/regex_two_embeddings_with_metadata.tflite new file mode 100644 index 0000000..ade8dd7 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/test/testdata/task/text/regex_two_embeddings_with_metadata.tflite Binary files differ
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/cc/utils/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/cc/utils/BUILD index fc6de34..5547beb 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/cc/utils/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/cc/utils/BUILD
@@ -16,7 +16,6 @@ tflite_deps = [ "@org_tensorflow//tensorflow/lite/core/shims:delegate_plugin", "@org_tensorflow//tensorflow/lite/core/shims:delegate_registry", - "@org_tensorflow//tensorflow/lite/core/shims:jni_initialization", "@org_tensorflow//tensorflow/lite/experimental/acceleration/configuration:delegate_plugin_converter", ], visibility = [
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/BUILD index 2d69942..06b3912 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/BUILD
@@ -85,6 +85,20 @@ }), ) +cc_library( + name = "universal_sentence_encoder_qa_op_resolver", + srcs = ["universal_sentence_encoder_qa_op_resolver.cc"], + hdrs = ["universal_sentence_encoder_qa_op_resolver.h"], + deps = [ + "//tensorflow_lite_support/custom_ops/kernel/ragged:py_tflite_registerer", # fixdeps: keep + "//tensorflow_lite_support/custom_ops/kernel/sentencepiece:py_tflite_registerer", # fixdeps: keep + "//tensorflow_lite_support/custom_ops/kernel/sentencepiece:sentencepiece_tokenizer_op", # fixdeps: keep + "@com_google_absl//absl/memory", + "@org_tensorflow//tensorflow/lite:op_resolver", + "@org_tensorflow//tensorflow/lite/kernels:builtin_ops", + ], +) + # Example usage: # bazel run -c opt \ # tensorflow_lite_support/examples/task/text/desktop:universal_sentence_encoder_qa_main \ @@ -96,10 +110,8 @@ "universal_sentence_encoder_qa_demo.cc", ], deps = [ + ":universal_sentence_encoder_qa_op_resolver", "//tensorflow_lite_support/cc/task/text:universal_sentence_encoder_qa", - "//tensorflow_lite_support/custom_ops/kernel/ragged:py_tflite_registerer", - "//tensorflow_lite_support/custom_ops/kernel/sentencepiece:py_tflite_registerer", - "//tensorflow_lite_support/custom_ops/kernel/sentencepiece:sentencepiece_tokenizer_op", "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/flags:parse", "@com_google_absl//absl/status",
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_demo.cc b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_demo.cc index 8ba00cb..a46c60a 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_demo.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_demo.cc
@@ -19,10 +19,15 @@ #include "absl/status/status.h" // from @com_google_absl #include "absl/strings/str_split.h" // from @com_google_absl #include "tensorflow_lite_support/cc/task/text/universal_sentence_encoder_qa.h" +#include "tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_op_resolver.h" + +namespace { +using tflite::task::text::CreateQACustomOpResolver; using tflite::task::text::RetrievalInput; using tflite::task::text::RetrievalOptions; using tflite::task::text::RetrievalOutput; -using tflite::task::text::retrieval::UniversalSentenceEncoderQA; +using tflite::task::text::UniversalSentenceEncoderQA; +} // namespace ABSL_FLAG(std::string, model_path, @@ -57,7 +62,8 @@ RetrievalOptions options; options.mutable_base_options()->mutable_model_file()->set_file_name( absl::GetFlag(FLAGS_model_path)); - auto status = UniversalSentenceEncoderQA::CreateFromOption(options); + auto status = UniversalSentenceEncoderQA::CreateFromOption( + options, CreateQACustomOpResolver()); CHECK_OK(status); std::unique_ptr<UniversalSentenceEncoderQA> client = std::move(status.value());
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_op_resolver.cc b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_op_resolver.cc new file mode 100644 index 0000000..21e4f26 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_op_resolver.cc
@@ -0,0 +1,47 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#include "tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_op_resolver.h" + +#include "absl/memory/memory.h" // from @com_google_absl +#include "tensorflow/lite/kernels/register.h" + +namespace tflite { +namespace ops { +namespace custom { +TfLiteRegistration* Register_SENTENCEPIECE_TOKENIZER(); +TfLiteRegistration* Register_RAGGED_TENSOR_TO_TENSOR(); +} // namespace custom +} // namespace ops +} // namespace tflite + +namespace tflite { +namespace task { +namespace text { + +// Creates custom op resolver for USE QA task. +std::unique_ptr<tflite::OpResolver> CreateQACustomOpResolver() { + auto resolver = absl::make_unique<tflite::ops::builtin::BuiltinOpResolver>(); + resolver->AddCustom( + "TFSentencepieceTokenizeOp", + ::tflite::ops::custom::Register_SENTENCEPIECE_TOKENIZER()); + resolver->AddCustom( + "RaggedTensorToTensor", + ::tflite::ops::custom::Register_RAGGED_TENSOR_TO_TENSOR()); + return resolver; +} + +} // namespace text +} // namespace task +} // namespace tflite
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_op_resolver.h b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_op_resolver.h new file mode 100644 index 0000000..87c405a --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/text/desktop/universal_sentence_encoder_qa_op_resolver.h
@@ -0,0 +1,33 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ + +#ifndef TENSORFLOW_LITE_SUPPORT_EXAMPLE_TASK_TEXT_DESKTOP_UNIVERSAL_SENTENCE_ENCODER_OP_RESOLVER_H_ +#define TENSORFLOW_LITE_SUPPORT_EXAMPLE_TASK_TEXT_DESKTOP_UNIVERSAL_SENTENCE_ENCODER_OP_RESOLVER_H_ + +#include <memory> + +#include "tensorflow/lite/op_resolver.h" + +namespace tflite { +namespace task { +namespace text { + +std::unique_ptr<tflite::OpResolver> CreateQACustomOpResolver(); + +} // namespace text +} // namespace task +} // namespace tflite + +#endif // TENSORFLOW_LITE_SUPPORT_EXAMPLE_TASK_TEXT_DESKTOP_UNIVERSAL_SENTENCE_ENCODER_OP_RESOLVER_H_
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/python/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/python/BUILD index baf5e784..7692df7 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/python/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/python/BUILD
@@ -53,3 +53,16 @@ "@absl_py//absl/flags", ], ) + +py_binary( + name = "image_embedder_demo", + srcs = ["image_embedder_demo.py"], + deps = [ + "//tensorflow_lite_support/python/task/core:task_options", + "//tensorflow_lite_support/python/task/processor/proto:embedding_options_pb2", + "//tensorflow_lite_support/python/task/vision:image_embedder", + "//tensorflow_lite_support/python/task/vision/core:tensor_image", + "@absl_py//absl:app", + "@absl_py//absl/flags", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/python/image_embedder_demo.py b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/python/image_embedder_demo.py new file mode 100644 index 0000000..24adda1 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/python/image_embedder_demo.py
@@ -0,0 +1,94 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Python demo tool for Image Embedder.""" + +import os + +from absl import app +from absl import flags + +from tensorflow_lite_support.python.task.core import task_options +from tensorflow_lite_support.python.task.processor.proto import embedding_options_pb2 +from tensorflow_lite_support.python.task.vision import image_embedder +from tensorflow_lite_support.python.task.vision.core import tensor_image + +FLAGS = flags.FLAGS + +flags.DEFINE_string("model_path", None, + "Absolute path to the \".tflite\" image embedder model.") +flags.DEFINE_string( + "first_image_path", None, + "Absolute path to the first image, whose feature vector will be extracted " + "and compared to the second image using cosine similarity. The image must " + "be RGB or RGBA (grayscale is not supported). The image EXIF orientation " + "flag, if any, is NOT taken into account.") +flags.DEFINE_string( + "second_image_path", None, + "Absolute path to the second image, whose feature vector will be extracted " + "and compared to the first image using cosine similarity. The image must " + "be RGB or RGBA (grayscale is not supported). The image EXIF orientation " + "flag, if any, is NOT taken into account.") +flags.DEFINE_bool( + "l2_normalize", False, + "If true, the raw feature vectors returned by the image embedder will be " + "normalized with L2-norm. Generally only needed if the model doesn't " + "already contain a L2_NORMALIZATION TFLite Op.") +flags.DEFINE_bool( + "quantize", False, + "If true, the raw feature vectors returned by the image embedder will be " + "quantized to 8 bit integers (uniform quantization) via post-processing " + "before cosine similarity is computed.") +flags.DEFINE_bool( + "use_coral", False, + "If true, inference will be delegated to a connected Coral Edge TPU device." +) + + +def build_options(): + base_options = task_options.BaseOptions( + model_file=task_options.ExternalFile(file_name=FLAGS.model_path), + use_coral=FLAGS.use_coral) + embedding_options = embedding_options_pb2.EmbeddingOptions( + l2_normalize=FLAGS.l2_normalize, quantize=FLAGS.quantize) + return image_embedder.ImageEmbedderOptions( + base_options=base_options, embedding_options=embedding_options) + + +def main(_) -> None: + # Creates embedder. + options = build_options() + embedder = image_embedder.ImageEmbedder.create_from_options(options) + + # Loads images. + first_image = tensor_image.TensorImage.from_file(FLAGS.first_image_path) + second_image = tensor_image.TensorImage.from_file(FLAGS.second_image_path) + + # Extracts both embeddings. + first_result = embedder.embed(first_image) + second_result = embedder.embed(second_image) + + # Gets consine similarity. + cosine_similarity = embedder.cosine_similarity( + first_result.embeddings[0].feature_vector, + second_result.embeddings[0].feature_vector) + print("The cosine similarity of %s and %s is %f" % + (os.path.basename(FLAGS.first_image_path), + os.path.basename(FLAGS.second_image_path), cosine_similarity)) + + +if __name__ == "__main__": + flags.mark_flag_as_required("model_path") + flags.mark_flag_as_required("first_image_path") + flags.mark_flag_as_required("second_image_path") + app.run(main)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/BUILD index 481fd8ec..b3009dc 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/BUILD
@@ -16,6 +16,8 @@ "//tensorflow_lite_support/cc/port:integral_types", "//tensorflow_lite_support/cc/port:status_macros", "//tensorflow_lite_support/cc/port:statusor", + "//tensorflow_lite_support/cc/task/vision/core:frame_buffer", + "//tensorflow_lite_support/cc/task/vision/utils:frame_buffer_common_utils", "@com_google_absl//absl/status", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:str_format",
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.cc b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.cc index efdcda9..d5c0c58 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.cc
@@ -30,6 +30,7 @@ #include "stb_image_write.h" // from @stblib #include "tensorflow_lite_support/cc/port/status_macros.h" #include "tensorflow_lite_support/cc/port/statusor.h" +#include "tensorflow_lite_support/cc/task/vision/utils/frame_buffer_common_utils.h" namespace tflite { namespace task { @@ -91,6 +92,25 @@ stbi_image_free(image->pixel_data); } +tflite::support::StatusOr<std::unique_ptr<FrameBuffer>> +CreateFrameBufferFromImageData(const ImageData& image) { + if (image.channels == 1) { + return CreateFromGrayRawBuffer(image.pixel_data, + {image.width, image.height}); + } + if (image.channels == 3) { + return CreateFromRgbRawBuffer(image.pixel_data, + {image.width, image.height}); + } else if (image.channels == 4) { + return CreateFromRgbaRawBuffer(image.pixel_data, + {image.width, image.height}); + } + return absl::InvalidArgumentError( + absl::StrFormat("Expected image with 1 (grayscale), 3 (RGB) or 4 (RGBA) " + "channels, found %d", + image.channels)); +} + } // namespace vision } // namespace task } // namespace tflite
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.h b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.h index 9e7e3ba..7de32ee9 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/examples/task/vision/desktop/utils/image_utils.h
@@ -19,6 +19,7 @@ #include "absl/strings/string_view.h" // from @com_google_absl #include "tensorflow_lite_support/cc/port/integral_types.h" #include "tensorflow_lite_support/cc/port/statusor.h" +#include "tensorflow_lite_support/cc/task/vision/core/frame_buffer.h" namespace tflite { namespace task { @@ -51,6 +52,9 @@ // Releases image pixel data memory. void ImageDataFree(ImageData* image); +// Creates the FrameBuffer object from the ImageData object. +tflite::support::StatusOr<std::unique_ptr<FrameBuffer>> +CreateFrameBufferFromImageData(const ImageData& image); } // namespace vision } // namespace task } // namespace tflite
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.h index a194b28..686a996 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.h
@@ -26,23 +26,19 @@ * * @param code Error code. * @param description Error description. - * @param error Pointer to the memory location where the created error should be - * saved. If `nil`, no error will be saved. + * @return A NSError instance. */ -+ (void)customErrorWithCode:(NSInteger)code - description:(NSString*)description - error:(NSError**)error; ++ (NSError*)customErrorWithCode:(NSInteger)code + description:(NSString*)description; /** * Creates and saves an error originating from the task library from a C library * error, TfLiteSupportError . * * @param supportError C library error. - * @param error Pointer to the memory location where the created error should be - * saved. If `nil`, no error will be saved. + * @return A NSError instance. */ -+ (void)errorFromTfLiteSupportError:(TfLiteSupportError*)supportError - error:(NSError**)error; ++ (NSError*)errorWithCError:(TfLiteSupportError*)supportError; /** * Allocates a block of memory with the specified size and returns a pointer to
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.m index 2f2d85a..a771a5a 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/sources/TFLCommonUtils.m
@@ -16,43 +16,37 @@ #import "tensorflow_lite_support/ios/sources/TFLCommon.h" /** Error domain of TensorFlow Lite Support related errors. */ -static NSString* const TFLSupportTaskErrorDomain = @"org.tensorflow.lite.tasks"; +static NSString *const TFLSupportTaskErrorDomain = @"org.tensorflow.lite.tasks"; @implementation TFLCommonUtils -+ (void)customErrorWithCode:(NSInteger)code - description:(NSString*)description - error:(NSError**)error { - if (error) - *error = - [NSError errorWithDomain:TFLSupportTaskErrorDomain - code:code - userInfo:@{NSLocalizedDescriptionKey : description}]; ++ (NSError *)customErrorWithCode:(NSInteger)code description:(NSString *)description { + return [NSError errorWithDomain:TFLSupportTaskErrorDomain + code:code + userInfo:@{NSLocalizedDescriptionKey : description}]; } -+ (void)errorFromTfLiteSupportError:(TfLiteSupportError*)supportError - error:(NSError**)error { - if (supportError && error) - *error = [NSError errorWithDomain:TFLSupportTaskErrorDomain - code:supportError->code - userInfo:@{ - NSLocalizedDescriptionKey : [NSString - stringWithCString:supportError->message - encoding:NSUTF8StringEncoding] - }]; ++ (NSError *)errorWithCError:(TfLiteSupportError *)supportError { + return [NSError + errorWithDomain:TFLSupportTaskErrorDomain + code:supportError->code + userInfo:@{ + NSLocalizedDescriptionKey : [NSString stringWithCString:supportError->message + encoding:NSUTF8StringEncoding] + }]; } -+ (void*)mallocWithSize:(size_t)memSize error:(NSError**)error { ++ (void *)mallocWithSize:(size_t)memSize error:(NSError **)error { if (!memSize) { - [TFLCommonUtils - customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError - description: - @"Invalid memory size passed for allocation of object." - error:error]; + if (error) { + *error = [TFLCommonUtils + customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError + description:@"Invalid memory size passed for allocation of object."]; + } return NULL; } - void* allocedMemory = malloc(memSize); + void *allocedMemory = malloc(memSize); if (!allocedMemory && memSize) { exit(-1); }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.h index 90864c7..5058f7c 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.h
@@ -13,12 +13,12 @@ limitations under the License. ==============================================================================*/ #include "tensorflow_lite_support/c/task/core/base_options.h" -#import "third_party/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.h" +#import "tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.h" NS_ASSUME_NONNULL_BEGIN @interface TFLBaseOptions (Helpers) -- (void)copyBaseOptionsToCBaseOptions:(TfLiteBaseOptions*)cBaseOptions; +- (void)copyToCOptions:(TfLiteBaseOptions*)cBaseOptions; @end NS_ASSUME_NONNULL_END
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.m index ddab0f7..0ade2372 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.m
@@ -16,7 +16,7 @@ @implementation TFLBaseOptions (Helpers) -- (void)copyBaseOptionsToCBaseOptions:(TfLiteBaseOptions*)cBaseOptions { +- (void)copyToCOptions:(TfLiteBaseOptions *)cBaseOptions { if (self.modelFile.filePath) { cBaseOptions->model_file.file_path = self.modelFile.filePath.UTF8String; }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.m index 1e536cd..826380f 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.m
@@ -25,8 +25,8 @@ return self; } -- (id)copyWithZone:(NSZone*)zone { - TFLCpuSettings* cpuSettings = [[TFLCpuSettings alloc] init]; +- (id)copyWithZone:(NSZone *)zone { + TFLCpuSettings *cpuSettings = [[TFLCpuSettings alloc] init]; [cpuSettings setNumThreads:self.numThreads]; @@ -46,8 +46,8 @@ return self; } -- (id)copyWithZone:(NSZone*)zone { - TFLComputeSettings* computeSettings = [[TFLComputeSettings alloc] init]; +- (id)copyWithZone:(NSZone *)zone { + TFLComputeSettings *computeSettings = [[TFLComputeSettings alloc] init]; [computeSettings setCpuSettings:self.cpuSettings]; @@ -59,8 +59,8 @@ @implementation TFLExternalFile @synthesize filePath; -- (id)copyWithZone:(NSZone*)zone { - TFLExternalFile* externalFile = [[TFLExternalFile alloc] init]; +- (id)copyWithZone:(NSZone *)zone { + TFLExternalFile *externalFile = [[TFLExternalFile alloc] init]; [externalFile setFilePath:self.filePath]; @@ -82,8 +82,8 @@ return self; } -- (id)copyWithZone:(NSZone*)zone { - TFLBaseOptions* baseOptions = [[TFLBaseOptions alloc] init]; +- (id)copyWithZone:(NSZone *)zone { + TFLBaseOptions *baseOptions = [[TFLBaseOptions alloc] init]; [baseOptions setModelFile:self.modelFile]; [baseOptions setComputeSettings:self.computeSettings];
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/BUILD index f6600e07..01e06225 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/BUILD
@@ -15,6 +15,17 @@ ) objc_library( + name = "TFLCategory", + srcs = [ + "sources/TFLCategory.m", + ], + hdrs = [ + "sources/TFLCategory.h", + ], + module_name = "TFLCategory", +) + +objc_library( name = "TFLClassificationResult", srcs = [ "sources/TFLClassificationResult.m", @@ -23,6 +34,23 @@ "sources/TFLClassificationResult.h", ], module_name = "TFLClassificationResult", + deps = [ + ":TFLCategory", + ], +) + +objc_library( + name = "TFLDetectionResult", + srcs = [ + "sources/TFLDetectionResult.m", + ], + hdrs = [ + "sources/TFLDetectionResult.h", + ], + module_name = "TFLDetectionResult", + deps = [ + ":TFLCategory", + ], ) objc_library( @@ -41,3 +69,50 @@ "//tensorflow_lite_support/ios/task/processor:TFLClassificationOptions", ], ) + +objc_library( + name = "TFLCategoryHelpers", + srcs = [ + "sources/TFLCategory+Helpers.m", + ], + hdrs = [ + "sources/TFLCategory+Helpers.h", + ], + module_name = "TFLCategoryHelpers", + deps = [ + "//tensorflow_lite_support/c/task/processor:category", + "//tensorflow_lite_support/ios/task/processor:TFLCategory", + ], +) + +objc_library( + name = "TFLClassificationResultHelpers", + srcs = [ + "sources/TFLClassificationResult+Helpers.m", + ], + hdrs = [ + "sources/TFLClassificationResult+Helpers.h", + ], + module_name = "TFLClassificationResultHelpers", + deps = [ + ":TFLCategoryHelpers", + "//tensorflow_lite_support/c/task/processor:classification_result", + "//tensorflow_lite_support/ios/task/processor:TFLClassificationResult", + ], +) + +objc_library( + name = "TFLDetectionResultHelpers", + srcs = [ + "sources/TFLDetectionResult+Helpers.m", + ], + hdrs = [ + "sources/TFLDetectionResult+Helpers.h", + ], + module_name = "TFLDetectionResultHelpers", + deps = [ + ":TFLCategoryHelpers", + "//tensorflow_lite_support/c/task/processor:detection_result", + "//tensorflow_lite_support/ios/task/processor:TFLDetectionResult", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.h new file mode 100644 index 0000000..6f515e46 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.h
@@ -0,0 +1,36 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#include "tensorflow_lite_support/c/task/processor/category.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TFLCategory (Helpers) + +/** + * Creates and retrurns a TFLCategory from a TfLiteCategory representing any + * result class retured by TFLite Task C Library Classification tasks. + * + * @param cCategory A result class returned by TFLite Task C Library + * Classification tasks + * + * @return Category of type TfLiteCategory which represents a result class in + * results returned by inference methods of the iOS TF Lite Task Classification + * tasks. + */ ++ (TFLCategory*)categoryWithCCategory:(TfLiteCategory*)cCategory; +@end + +NS_ASSUME_NONNULL_END
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.m new file mode 100644 index 0000000..827d2c8 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.m
@@ -0,0 +1,38 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#import "tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.h" + +@implementation TFLCategory (Helpers) + ++ (TFLCategory *)categoryWithCCategory:(TfLiteCategory *)cCategory { + if (cCategory == nil) return nil; + + TFLCategory *category = [[TFLCategory alloc] init]; + + if (cCategory->display_name != nil) { + category.displayName = [NSString stringWithCString:cCategory->display_name + encoding:NSUTF8StringEncoding]; + } + + if (cCategory->label != nil) { + category.label = [NSString stringWithCString:cCategory->label encoding:NSUTF8StringEncoding]; + } + + category.score = cCategory->score; + category.classIndex = (NSInteger)cCategory->index; + + return category; +} +@end
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h new file mode 100644 index 0000000..9188fc0 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h
@@ -0,0 +1,37 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#import <Foundation/Foundation.h> + +NS_ASSUME_NONNULL_BEGIN + +/** Encapsulates information about a class in the classification results. */ +@interface TFLCategory : NSObject + +/** Display name of the class. */ +@property(nonatomic, copy) NSString* displayName; + +/** Class name of the class . */ +@property(nonatomic, copy) NSString* label; + +/** Confidence score for this class . */ +@property(nonatomic, assign) float score; + +/** The index of the class in the corresponding label map, usually packed in the + * TFLite Model Metadata. */ +@property(nonatomic, assign) NSInteger classIndex; + +@end + +NS_ASSUME_NONNULL_END
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory.m new file mode 100644 index 0000000..430b2385 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLCategory.m
@@ -0,0 +1,22 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#import "tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h" + +@implementation TFLCategory +@synthesize displayName; +@synthesize label; +@synthesize score; +@synthesize classIndex; +@end
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.h index 78a1f965..33ecd08 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.h
@@ -13,14 +13,13 @@ limitations under the License. ==============================================================================*/ #include "tensorflow_lite_support/c/task/processor/classification_options.h" -#import "third_party/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.h" NS_ASSUME_NONNULL_BEGIN @interface TFLClassificationOptions (Helpers) -- (BOOL)copyClassificationOptionsToCClassificationOptions: - (TfLiteClassificationOptions*)cClassificationOptions - error:(NSError**)error; +- (BOOL)copyToCOptions:(TfLiteClassificationOptions*)cClassificationOptions + error:(NSError**)error; - (void)deleteCStringArraysOfClassificationOptions: (TfLiteClassificationOptions*)cClassificationOptions;
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.m index 07254ab..9307f9e 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.m
@@ -18,35 +18,31 @@ @implementation TFLClassificationOptions (Helpers) -+ (char**)cStringArrayFromNSArray:(NSArray<NSString*>*)strings - error:(NSError**)error { ++ (char **)cStringArrayFromNSArray:(NSArray<NSString *> *)strings error:(NSError **)error { if (strings.count <= 0) { - [TFLCommonUtils - customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError - description: - @"Invalid length of strings found for list type options." - error:error]; + if (error) { + *error = [TFLCommonUtils + customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError + description:@"Invalid length of strings found for list type options."]; + } return NULL; } - char** cStrings = (char**)calloc(strings.count, sizeof(char*)); + char **cStrings = (char **)calloc(strings.count, sizeof(char *)); if (!cStrings) { - [TFLCommonUtils - customErrorWithCode:TFLSupportErrorCodeInternalError - description:@"Could not initialize list type options." - error:error]; + if (error) { + *error = [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeInternalError + description:@"Could not initialize list type options."]; + } return nil; } for (NSInteger i = 0; i < strings.count; i++) { - char* cString = [TFLCommonUtils - mallocWithSize:[strings[i] - lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + - 1 + char *cString = [TFLCommonUtils + mallocWithSize:[strings[i] lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1 error:error]; - if (!cString) - return nil; + if (!cString) return nil; strcpy(cString, strings[i].UTF8String); } @@ -54,7 +50,7 @@ return cStrings; } -+ (void)deleteCStringsArray:(char**)cStrings count:(int)count { ++ (void)deleteCStringsArray:(char **)cStrings count:(int)count { for (NSInteger i = 0; i < count; i++) { free(cStrings[i]); } @@ -62,57 +58,49 @@ free(cStrings); } -- (BOOL)copyClassificationOptionsToCClassificationOptions: - (TfLiteClassificationOptions*)cClassificationOptions - error:(NSError**)error { +- (BOOL)copyToCOptions:(TfLiteClassificationOptions *)cClassificationOptions + error:(NSError **)error { cClassificationOptions->score_threshold = self.scoreThreshold; cClassificationOptions->max_results = (int)self.maxResults; if (self.labelDenyList) { - char** cClassNameBlackList = - [TFLClassificationOptions cStringArrayFromNSArray:self.labelDenyList - error:error]; + char **cClassNameBlackList = + [TFLClassificationOptions cStringArrayFromNSArray:self.labelDenyList error:error]; if (!cClassNameBlackList) { return NO; } cClassificationOptions->label_denylist.list = cClassNameBlackList; - cClassificationOptions->label_denylist.length = - (int)self.labelDenyList.count; + cClassificationOptions->label_denylist.length = (int)self.labelDenyList.count; } if (self.labelAllowList) { - char** cClassNameWhiteList = - [TFLClassificationOptions cStringArrayFromNSArray:self.labelAllowList - error:error]; + char **cClassNameWhiteList = + [TFLClassificationOptions cStringArrayFromNSArray:self.labelAllowList error:error]; if (!cClassNameWhiteList) { return NO; } cClassificationOptions->label_allowlist.list = cClassNameWhiteList; - cClassificationOptions->label_allowlist.length = - (int)self.labelAllowList.count; + cClassificationOptions->label_allowlist.length = (int)self.labelAllowList.count; } if (self.displayNamesLocal) { - cClassificationOptions->display_names_local = - (char*)self.displayNamesLocal.UTF8String; + cClassificationOptions->display_names_local = (char *)self.displayNamesLocal.UTF8String; } return YES; } - (void)deleteCStringArraysOfClassificationOptions: - (TfLiteClassificationOptions*)cClassificationOptions { + (TfLiteClassificationOptions *)cClassificationOptions { if (self.labelAllowList) { - [TFLClassificationOptions - deleteCStringsArray:cClassificationOptions->label_allowlist.list - count:cClassificationOptions->label_allowlist.length]; + [TFLClassificationOptions deleteCStringsArray:cClassificationOptions->label_allowlist.list + count:cClassificationOptions->label_allowlist.length]; } if (self.labelDenyList) { - [TFLClassificationOptions - deleteCStringsArray:cClassificationOptions->label_denylist.list - count:cClassificationOptions->label_denylist.length]; + [TFLClassificationOptions deleteCStringsArray:cClassificationOptions->label_denylist.list + count:cClassificationOptions->label_denylist.length]; } } @end
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.m index dca232d6..784f782e 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.m
@@ -30,9 +30,8 @@ return self; } -- (id)copyWithZone:(NSZone*)zone { - TFLClassificationOptions* classificationOptions = - [[TFLClassificationOptions alloc] init]; +- (id)copyWithZone:(NSZone *)zone { + TFLClassificationOptions *classificationOptions = [[TFLClassificationOptions alloc] init]; [classificationOptions setScoreThreshold:self.scoreThreshold]; [classificationOptions setMaxResults:self.maxResults];
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.h similarity index 69% rename from third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.h rename to third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.h index c52876e..9c8b92c 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.h
@@ -1,4 +1,4 @@ -/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -12,16 +12,12 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#import <Foundation/Foundation.h> -#import "third_party/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h" - #include "tensorflow_lite_support/c/task/processor/classification_result.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h" NS_ASSUME_NONNULL_BEGIN -/** Helper utility for conversion between TFLite Task C Library Classification - * Results and iOS Classification Results . */ -@interface TFLClassificationUtils : NSObject +@interface TFLClassificationResult (Helpers) /** * Creates and retrurns a TFLClassificationResult from a @@ -34,13 +30,8 @@ * @return Classification Result of type TFLClassificationResult to be returned * by inference methods of the iOS TF Lite Task Classification tasks. */ -+ (TFLClassificationResult*)classificationResultFromCClassificationResults: ++ (TFLClassificationResult*)classificationResultWithCResult: (TfLiteClassificationResult*)cClassificationResult; - -- (instancetype)init NS_UNAVAILABLE; - -+ (instancetype)new NS_UNAVAILABLE; - @end NS_ASSUME_NONNULL_END
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.m new file mode 100644 index 0000000..78021ce --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.m
@@ -0,0 +1,44 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#import "tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.h" + +@implementation TFLClassificationResult (Helpers) + ++ (TFLClassificationResult *)classificationResultWithCResult: + (TfLiteClassificationResult *)cClassificationResult { + if (cClassificationResult == nil) return nil; + + NSMutableArray *classificationHeads = [[NSMutableArray alloc] init]; + for (int i = 0; i < cClassificationResult->size; i++) { + TfLiteClassifications cClassifications = cClassificationResult->classifications[i]; + NSMutableArray *classes = [[NSMutableArray alloc] init]; + for (int j = 0; j < cClassifications.size; j++) { + TfLiteCategory cCategory = cClassifications.categories[j]; + + TFLCategory *resultCategory = [TFLCategory categoryWithCCategory:&cCategory]; + [classes addObject:resultCategory]; + } + TFLClassifications *classificationHead = [[TFLClassifications alloc] init]; + classificationHead.categories = classes; + classificationHead.headIndex = i; + [classificationHeads addObject:classificationHead]; + } + + TFLClassificationResult *classificationResult = [[TFLClassificationResult alloc] init]; + classificationResult.classifications = classificationHeads; + return classificationResult; +} +@end
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h index c0d6fb3..500ec8fa 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h
@@ -13,27 +13,10 @@ limitations under the License. ==============================================================================*/ #import <Foundation/Foundation.h> +#import "tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h" NS_ASSUME_NONNULL_BEGIN -/** Encapsulates information about a class in the classification results. */ -@interface TFLCategory : NSObject - -/** Display name of the class. */ -@property(nonatomic, copy) NSString* displayName; - -/** Class name of the class . */ -@property(nonatomic, copy) NSString* label; - -/** Confidence score for this class . */ -@property(nonatomic, assign) float score; - -/** The index of the class in the corresponding label map, usually packed in the - * TFLite Model Metadata. */ -@property(nonatomic, assign) NSInteger classIndex; - -@end - /** Encapsulates list of predicted classes (aka labels) for a given image * classifier head. */ @interface TFLClassifications : NSObject
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.m index febf230b..7d6310d6 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.m
@@ -14,13 +14,6 @@ ==============================================================================*/ #import "tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h" -@implementation TFLCategory -@synthesize displayName; -@synthesize label; -@synthesize score; -@synthesize classIndex; -@end - @implementation TFLClassifications @synthesize headIndex; @synthesize categories;
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.h new file mode 100644 index 0000000..81efbcc1 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.h
@@ -0,0 +1,35 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#include "tensorflow_lite_support/c/task/processor/detection_result.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface TFLDetectionResult (Helpers) +/** + * Creates and retrurns a TFLDetectionResult from a TfLiteDetectionResult + * returned by TFLite Task C Library Object Detection task. + * + * @param cDetectionResult Detection results returned by TFLite Task C Library + * Object Detection task. + * + * @return Detection Result of type TFLDetectionResult to be returned by + * inference methods of the iOS TF Lite Task Object Detection task. + */ ++ (TFLDetectionResult*)detectionResultWithCResult: + (TfLiteDetectionResult*)cDetectionResult; +@end + +NS_ASSUME_NONNULL_END
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.m new file mode 100644 index 0000000..799bcda --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.m
@@ -0,0 +1,46 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#import "tensorflow_lite_support/ios/task/processor/sources/TFLCategory+Helpers.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.h" + +@implementation TFLDetectionResult (Helpers) + ++ (TFLDetectionResult *)detectionResultWithCResult: + (TfLiteDetectionResult *)cDetectionResult { + if (cDetectionResult == nil) return nil; + + NSMutableArray *detections = [[NSMutableArray alloc] init]; + for (int i = 0; i < cDetectionResult->size; i++) { + TfLiteDetection cDetection = cDetectionResult->detections[i]; + NSMutableArray *categories = [[NSMutableArray alloc] init]; + for (int j = 0; j < cDetection.size; j++) { + TfLiteCategory cCategory = cDetection.categories[j]; + + TFLCategory *resultCategory = [TFLCategory categoryWithCCategory:&cCategory]; + [categories addObject:resultCategory]; + } + TFLDetection *detection = [[TFLDetection alloc] init]; + detection.categories = categories; + detection.boundingBox = + CGRectMake(cDetection.bounding_box.origin_x, cDetection.bounding_box.origin_y, + cDetection.bounding_box.width, cDetection.bounding_box.height); + [detections addObject:detection]; + } + + TFLDetectionResult *detectionResult = [[TFLDetectionResult alloc] init]; + detectionResult.detections = detections; + return detectionResult; +} +@end
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.h new file mode 100644 index 0000000..4d7fc0c --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.h
@@ -0,0 +1,45 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#import <CoreGraphics/CoreGraphics.h> +#import <Foundation/Foundation.h> + +#import "tensorflow_lite_support/ios/task/processor/sources/TFLCategory.h" + +NS_ASSUME_NONNULL_BEGIN + +/** Encapsulates list of predicted classes (aka labels) and bounding box for a + * detected object. */ +@interface TFLDetection : NSObject + +/** + * The index of the image classifier head these classes refer to. This is useful + * for multi-head models. + */ +@property(nonatomic, assign) CGRect boundingBox; + +/** The array of predicted classes, usually sorted by descending scores + * (e.g.from high to low probability). */ +@property(nonatomic, copy) NSArray<TFLCategory*>* categories; + +@end + +/** Encapsulates results of any object detection task. */ +@interface TFLDetectionResult : NSObject + +@property(nonatomic, copy) NSArray<TFLDetection*>* detections; + +@end + +NS_ASSUME_NONNULL_END
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.m new file mode 100644 index 0000000..2b7d3a1 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.m
@@ -0,0 +1,28 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#import "tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.h" + +@implementation TFLDetection + +@synthesize boundingBox; +@synthesize categories; + +@end + +@implementation TFLDetectionResult + +@synthesize detections; + +@end
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/BUILD deleted file mode 100644 index 13b9809c..0000000 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/BUILD +++ /dev/null
@@ -1,19 +0,0 @@ -package( - default_visibility = ["//tensorflow_lite_support:__subpackages__"], - licenses = ["notice"], # Apache 2.0 -) - -objc_library( - name = "TFLClassificationUtils", - srcs = [ - "sources/TFLClassificationUtils.m", - ], - hdrs = [ - "sources/TFLClassificationUtils.h", - ], - module_name = "TFLClassificationUtils", - deps = [ - "//tensorflow_lite_support/c/task/processor:classification_result", - "//tensorflow_lite_support/ios/task/processor:TFLClassificationResult", - ], -)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.m deleted file mode 100644 index b5d884d..0000000 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.m +++ /dev/null
@@ -1,61 +0,0 @@ -/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ==============================================================================*/ -#import "tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.h" - -@implementation TFLClassificationUtils - -+ (TFLClassificationResult*)classificationResultFromCClassificationResults: - (TfLiteClassificationResult*)cClassificationResult { - if (cClassificationResult == nil) - return nil; - - NSMutableArray* classificationHeads = [[NSMutableArray alloc] init]; - for (int i = 0; i < cClassificationResult->size; i++) { - TfLiteClassifications cClassifications = - cClassificationResult->classifications[i]; - NSMutableArray* classes = [[NSMutableArray alloc] init]; - for (int j = 0; j < cClassifications.size; j++) { - TfLiteCategory cCategory = cClassifications.categories[j]; - TFLCategory* resultCategory = [[TFLCategory alloc] init]; - - if (cCategory.display_name != nil) { - resultCategory.displayName = - [NSString stringWithCString:cCategory.display_name - encoding:NSUTF8StringEncoding]; - } - - if (cCategory.label != nil) { - resultCategory.label = - [NSString stringWithCString:cCategory.label - encoding:NSUTF8StringEncoding]; - } - - resultCategory.score = cCategory.score; - resultCategory.classIndex = (NSInteger)cCategory.index; - [classes addObject:resultCategory]; - } - TFLClassifications* classificationHead = [[TFLClassifications alloc] init]; - classificationHead.categories = classes; - classificationHead.headIndex = i; - [classificationHeads addObject:classificationHead]; - } - - TFLClassificationResult* classificationResult = - [[TFLClassificationResult alloc] init]; - classificationResult.classifications = classificationHeads; - return classificationResult; -} - -@end
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLBertNLClassifier.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLBertNLClassifier.m index 8c45ee6..e9d3b3d 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLBertNLClassifier.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLBertNLClassifier.m
@@ -25,7 +25,7 @@ @interface TFLBertNLClassifier () /** BertNLClassifier backed by C API */ -@property(nonatomic) TfLiteBertNLClassifier* bertNLClassifier; +@property(nonatomic) TfLiteBertNLClassifier *bertNLClassifier; @end @implementation TFLBertNLClassifier @@ -34,28 +34,24 @@ TfLiteBertNLClassifierDelete(_bertNLClassifier); } -+ (instancetype)bertNLClassifierWithModelPath:(NSString*)modelPath { - TfLiteBertNLClassifier* classifier = - TfLiteBertNLClassifierCreate(modelPath.UTF8String); ++ (instancetype)bertNLClassifierWithModelPath:(NSString *)modelPath { + TfLiteBertNLClassifier *classifier = TfLiteBertNLClassifierCreate(modelPath.UTF8String); _GTMDevAssert(classifier, @"Failed to create BertNLClassifier"); return [[TFLBertNLClassifier alloc] initWithBertNLClassifier:classifier]; } -+ (instancetype)bertNLClassifierWithModelPath:(NSString*)modelPath - options: - (TFLBertNLClassifierOptions*)options { - // Note that maxSeqLen has been deprecated. Passing it to the C API is a - // no-op. ++ (instancetype)bertNLClassifierWithModelPath:(NSString *)modelPath + options:(TFLBertNLClassifierOptions *)options { + // Note that maxSeqLen has been deprecated. Passing it to the C API is a no-op. TfLiteBertNLClassifierOptions cOptions = {.max_seq_len = options.maxSeqLen}; - TfLiteBertNLClassifier* classifier = + TfLiteBertNLClassifier *classifier = TfLiteBertNLClassifierCreateFromOptions(modelPath.UTF8String, &cOptions); _GTMDevAssert(classifier, @"Failed to create BertNLClassifier"); return [[TFLBertNLClassifier alloc] initWithBertNLClassifier:classifier]; } -- (instancetype)initWithBertNLClassifier: - (TfLiteBertNLClassifier*)bertNLClassifier { +- (instancetype)initWithBertNLClassifier:(TfLiteBertNLClassifier *)bertNLClassifier { self = [super init]; if (self) { _bertNLClassifier = bertNLClassifier; @@ -63,11 +59,9 @@ return self; } -- (NSDictionary<NSString*, NSNumber*>*)classifyWithText:(NSString*)text { - Categories* cCategories = - TfLiteBertNLClassifierClassify(_bertNLClassifier, text.UTF8String); - NSMutableDictionary<NSString*, NSNumber*>* ret = - [NSMutableDictionary dictionary]; +- (NSDictionary<NSString *, NSNumber *> *)classifyWithText:(NSString *)text { + Categories *cCategories = TfLiteBertNLClassifierClassify(_bertNLClassifier, text.UTF8String); + NSMutableDictionary<NSString *, NSNumber *> *ret = [NSMutableDictionary dictionary]; for (int i = 0; i < cCategories->size; i++) { Category cCategory = cCategories->categories[i]; [ret setValue:[NSNumber numberWithDouble:cCategory.score]
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLNLClassifier.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLNLClassifier.m index 39eb15c..8d21a111 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLNLClassifier.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Sources/TFLNLClassifier.m
@@ -30,7 +30,7 @@ @interface TFLNLClassifier () /** NLClassifier backed by C API */ -@property(nonatomic) TfLiteNLClassifier* nlClassifier; +@property(nonatomic) TfLiteNLClassifier *nlClassifier; @end @implementation TFLNLClassifier @@ -39,8 +39,8 @@ TfLiteNLClassifierDelete(_nlClassifier); } -+ (instancetype)nlClassifierWithModelPath:(NSString*)modelPath - options:(TFLNLClassifierOptions*)options { ++ (instancetype)nlClassifierWithModelPath:(NSString *)modelPath + options:(TFLNLClassifierOptions *)options { TfLiteNLClassifierOptions cOptions = { .input_tensor_index = options.inputTensorIndex, .output_score_tensor_index = options.outputScoreTensorIndex, @@ -48,13 +48,13 @@ .input_tensor_name = options.inputTensorName.UTF8String, .output_score_tensor_name = options.outputScoreTensorName.UTF8String, .output_label_tensor_name = options.outputLabelTensorName.UTF8String}; - TfLiteNLClassifier* classifier = + TfLiteNLClassifier *classifier = TfLiteNLClassifierCreateFromOptions(modelPath.UTF8String, &cOptions); _GTMDevAssert(classifier, @"Failed to create NLClassifier"); return [[TFLNLClassifier alloc] initWithNLClassifier:classifier]; } -- (instancetype)initWithNLClassifier:(TfLiteNLClassifier*)nlClassifier { +- (instancetype)initWithNLClassifier:(TfLiteNLClassifier *)nlClassifier { self = [super init]; if (self) { _nlClassifier = nlClassifier; @@ -62,11 +62,9 @@ return self; } -- (NSDictionary<NSString*, NSNumber*>*)classifyWithText:(NSString*)text { - Categories* cCategories = - TfLiteNLClassifierClassify(_nlClassifier, text.UTF8String); - NSMutableDictionary<NSString*, NSNumber*>* ret = - [NSMutableDictionary dictionary]; +- (NSDictionary<NSString *, NSNumber *> *)classifyWithText:(NSString *)text { + Categories *cCategories = TfLiteNLClassifierClassify(_nlClassifier, text.UTF8String); + NSMutableDictionary<NSString *, NSNumber *> *ret = [NSMutableDictionary dictionary]; for (int i = 0; i < cCategories->size; i++) { Category cCategory = cCategories->categories[i]; [ret setValue:[NSNumber numberWithDouble:cCategory.score]
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLBertNLClassifierTest.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLBertNLClassifierTest.m index 407be10..9734fe79 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLBertNLClassifierTest.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLBertNLClassifierTest.m
@@ -19,8 +19,8 @@ NS_ASSUME_NONNULL_BEGIN @interface TFLBertNLClassifierTest : XCTestCase -@property(nonatomic, nullable) NSString* bertModelPath; -@property(nonatomic, nullable) TFLBertNLClassifierOptions* modelOptions; +@property(nonatomic, nullable) NSString *bertModelPath; +@property(nonatomic, nullable) TFLBertNLClassifierOptions *modelOptions; @end @implementation TFLBertNLClassifierTest @@ -28,31 +28,30 @@ - (void)setUp { [super setUp]; - NSBundle* bundle = [NSBundle bundleForClass:[self class]]; - self.bertModelPath = [bundle pathForResource:@"bert_nl_classifier" - ofType:@"tflite"]; + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + self.bertModelPath = [bundle pathForResource:@"bert_nl_classifier" ofType:@"tflite"]; } - (void)testClassifyPositiveResult { - TFLBertNLClassifier* bertNLClassifier = + TFLBertNLClassifier *bertNLClassifier = [TFLBertNLClassifier bertNLClassifierWithModelPath:self.bertModelPath]; XCTAssertNotNil(bertNLClassifier); - NSDictionary<NSString*, NSNumber*>* categories = [bertNLClassifier - classifyWithText:@"it's a charming and often affecting journey"]; + NSDictionary<NSString *, NSNumber *> *categories = + [bertNLClassifier classifyWithText:@"it's a charming and often affecting journey"]; XCTAssertGreaterThan([categories[@"positive"] doubleValue], [categories[@"negative"] doubleValue]); } - (void)testClassifyNegativeResult { - TFLBertNLClassifier* bertNLClassifier = + TFLBertNLClassifier *bertNLClassifier = [TFLBertNLClassifier bertNLClassifierWithModelPath:self.bertModelPath]; XCTAssertNotNil(bertNLClassifier); - NSDictionary<NSString*, NSNumber*>* categories = + NSDictionary<NSString *, NSNumber *> *categories = [bertNLClassifier classifyWithText:@"unflinchingly bleak and desperate"]; XCTAssertGreaterThan([categories[@"negative"] doubleValue], @@ -63,14 +62,14 @@ self.modelOptions = [[TFLBertNLClassifierOptions alloc] init]; [self.modelOptions setMaxSeqLen:128]; - TFLBertNLClassifier* bertNLClassifier = + TFLBertNLClassifier *bertNLClassifier = [TFLBertNLClassifier bertNLClassifierWithModelPath:self.bertModelPath options:self.modelOptions]; XCTAssertNotNil(bertNLClassifier); - NSDictionary<NSString*, NSNumber*>* categories = [bertNLClassifier - classifyWithText:@"it's a charming and often affecting journey"]; + NSDictionary<NSString *, NSNumber *> *categories = + [bertNLClassifier classifyWithText:@"it's a charming and often affecting journey"]; XCTAssertGreaterThan([categories[@"positive"] doubleValue], [categories[@"negative"] doubleValue]); @@ -80,13 +79,13 @@ self.modelOptions = [[TFLBertNLClassifierOptions alloc] init]; [self.modelOptions setMaxSeqLen:128]; - TFLBertNLClassifier* bertNLClassifier = + TFLBertNLClassifier *bertNLClassifier = [TFLBertNLClassifier bertNLClassifierWithModelPath:self.bertModelPath options:self.modelOptions]; XCTAssertNotNil(bertNLClassifier); - NSDictionary<NSString*, NSNumber*>* categories = + NSDictionary<NSString *, NSNumber *> *categories = [bertNLClassifier classifyWithText:@"unflinchingly bleak and desperate"]; XCTAssertGreaterThan([categories[@"negative"] doubleValue],
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLNLClassifierTest.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLNLClassifierTest.m index 1dcf08a..40814ac 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLNLClassifierTest.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/nlclassifier/Tests/TFLNLClassifierTest.m
@@ -19,8 +19,8 @@ NS_ASSUME_NONNULL_BEGIN @interface TFLNLClassifierTest : XCTestCase -@property(nonatomic, nullable) NSString* modelPath; -@property(nonatomic, nullable) TFLNLClassifierOptions* modelOptions; +@property(nonatomic, nullable) NSString *modelPath; +@property(nonatomic, nullable) TFLNLClassifierOptions *modelOptions; @end @implementation TFLNLClassifierTest @@ -28,38 +28,34 @@ - (void)setUp { [super setUp]; - NSBundle* bundle = [NSBundle bundleForClass:[self class]]; - self.modelPath = - [bundle pathForResource:@"test_model_nl_classifier_with_regex_tokenizer" - ofType:@"tflite"]; + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + self.modelPath = [bundle pathForResource:@"test_model_nl_classifier_with_regex_tokenizer" + ofType:@"tflite"]; self.modelOptions = [[TFLNLClassifierOptions alloc] init]; [self.modelOptions setInputTensorName:@"input_text"]; [self.modelOptions setOutputScoreTensorName:@"probability"]; } - (void)testClassifyPositiveResult { - TFLNLClassifier* nlClassifier = - [TFLNLClassifier nlClassifierWithModelPath:self.modelPath - options:self.modelOptions]; + TFLNLClassifier *nlClassifier = [TFLNLClassifier nlClassifierWithModelPath:self.modelPath + options:self.modelOptions]; XCTAssertNotNil(nlClassifier); - NSDictionary<NSString*, NSNumber*>* categories = - [nlClassifier classifyWithText:@"This is the best movie I’ve seen in " - @"recent years. Strongly recommend it!"]; + NSDictionary<NSString *, NSNumber *> *categories = [nlClassifier + classifyWithText:@"This is the best movie I’ve seen in recent years. Strongly recommend it!"]; XCTAssertGreaterThan([categories[@"Positive"] doubleValue], [categories[@"Negative"] doubleValue]); } - (void)testClassifyNegativeResult { - TFLNLClassifier* nlClassifier = - [TFLNLClassifier nlClassifierWithModelPath:self.modelPath - options:self.modelOptions]; + TFLNLClassifier *nlClassifier = [TFLNLClassifier nlClassifierWithModelPath:self.modelPath + options:self.modelOptions]; XCTAssertNotNil(nlClassifier); - NSDictionary<NSString*, NSNumber*>* categories = + NSDictionary<NSString *, NSNumber *> *categories = [nlClassifier classifyWithText:@"What a waste of my time."]; XCTAssertGreaterThan([categories[@"Negative"] doubleValue],
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Sources/TFLBertQuestionAnswerer.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Sources/TFLBertQuestionAnswerer.m index b470c46..a07f875 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Sources/TFLBertQuestionAnswerer.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Sources/TFLBertQuestionAnswerer.m
@@ -25,7 +25,7 @@ @interface TFLBertQuestionAnswerer () /** BertQuestionAnswerer backed by C API */ -@property(nonatomic) TfLiteBertQuestionAnswerer* bertQuestionAnswerer; +@property(nonatomic) TfLiteBertQuestionAnswerer *bertQuestionAnswerer; @end @implementation TFLBertQuestionAnswerer @@ -34,16 +34,14 @@ TfLiteBertQuestionAnswererDelete(_bertQuestionAnswerer); } -+ (instancetype)questionAnswererWithModelPath:(NSString*)modelPath { - TfLiteBertQuestionAnswerer* bert_qa = - TfLiteBertQuestionAnswererCreate(modelPath.UTF8String); ++ (instancetype)questionAnswererWithModelPath:(NSString *)modelPath { + TfLiteBertQuestionAnswerer *bert_qa = TfLiteBertQuestionAnswererCreate(modelPath.UTF8String); _GTMDevAssert(bert_qa, @"Failed to create BertQuestionAnswerer"); return [[TFLBertQuestionAnswerer alloc] initWithBertQuestionAnswerer:bert_qa]; } -- (instancetype)initWithBertQuestionAnswerer: - (TfLiteBertQuestionAnswerer*)bertQuestionAnswerer { +- (instancetype)initWithBertQuestionAnswerer:(TfLiteBertQuestionAnswerer *)bertQuestionAnswerer { self = [super init]; if (self) { _bertQuestionAnswerer = bertQuestionAnswerer; @@ -51,17 +49,14 @@ return self; } -- (NSArray<TFLQAAnswer*>*)answerWithContext:(NSString*)context - question:(NSString*)question { - TfLiteQaAnswers* cAnswers = TfLiteBertQuestionAnswererAnswer( +- (NSArray<TFLQAAnswer *> *)answerWithContext:(NSString *)context question:(NSString *)question { + TfLiteQaAnswers *cAnswers = TfLiteBertQuestionAnswererAnswer( _bertQuestionAnswerer, context.UTF8String, question.UTF8String); - NSMutableArray<TFLQAAnswer*>* ret = - [NSMutableArray arrayWithCapacity:cAnswers->size]; + NSMutableArray<TFLQAAnswer *> *ret = [NSMutableArray arrayWithCapacity:cAnswers->size]; for (int i = 0; i < cAnswers->size; i++) { TfLiteQaAnswer cAnswer = cAnswers->answers[i]; - TFLQAAnswer* answer = [[TFLQAAnswer alloc] init]; - struct TFLPos pos = { - .start = cAnswer.start, .end = cAnswer.end, .logit = cAnswer.logit}; + TFLQAAnswer *answer = [[TFLQAAnswer alloc] init]; + struct TFLPos pos = {.start = cAnswer.start, .end = cAnswer.end, .logit = cAnswer.logit}; [answer setPos:pos]; [answer setText:[NSString stringWithUTF8String:cAnswer.text]]; [ret addObject:answer];
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Tests/TFLBertQuestionAnswererTest.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Tests/TFLBertQuestionAnswererTest.m index ac4a1d3..9061063 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Tests/TFLBertQuestionAnswererTest.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/text/qa/Tests/TFLBertQuestionAnswererTest.m
@@ -16,7 +16,7 @@ #import <XCTest/XCTest.h> -static NSString* const kContext = +static NSString *const kContext = @"The role of teacher is often formal and ongoing, carried out at a school " "or other place of formal education. In many countries, a person who " "wishes to become a teacher must first obtain specified professional " @@ -27,12 +27,12 @@ "continuing professional development. Teachers may use a lesson plan to " "facilitate student learning, providing a course of study which is called " "the curriculum."; -static NSString* const kQuestion = @"What is a course of study called?"; -static NSString* const kAnswer = @"the curriculum."; +static NSString *const kQuestion = @"What is a course of study called?"; +static NSString *const kAnswer = @"the curriculum."; @interface TFLBertQuestionAnswererTest : XCTestCase -@property(nonatomic, nullable) NSString* mobileBertModelPath; -@property(nonatomic, nullable) NSString* albertModelPath; +@property(nonatomic, nullable) NSString *mobileBertModelPath; +@property(nonatomic, nullable) NSString *albertModelPath; @end @implementation TFLBertQuestionAnswererTest @@ -40,33 +40,32 @@ - (void)setUp { [super setUp]; - NSBundle* bundle = [NSBundle bundleForClass:[self class]]; - self.mobileBertModelPath = [bundle pathForResource:@"mobilebert_with_metadata" - ofType:@"tflite"]; - self.albertModelPath = [bundle pathForResource:@"albert_with_metadata" - ofType:@"tflite"]; + NSBundle *bundle = [NSBundle bundleForClass:[self class]]; + self.mobileBertModelPath = [bundle pathForResource:@"mobilebert_with_metadata" ofType:@"tflite"]; + self.albertModelPath = [bundle pathForResource:@"albert_with_metadata" ofType:@"tflite"]; } - (void)testInitMobileBert { - TFLBertQuestionAnswerer* mobileBertAnswerer = [TFLBertQuestionAnswerer - questionAnswererWithModelPath:self.mobileBertModelPath]; + TFLBertQuestionAnswerer* mobileBertAnswerer = + [TFLBertQuestionAnswerer questionAnswererWithModelPath:self.mobileBertModelPath]; XCTAssertNotNil(mobileBertAnswerer); NSArray<TFLQAAnswer*>* answers = - [mobileBertAnswerer answerWithContext:kContext question:kQuestion]; + [mobileBertAnswerer answerWithContext:kContext question:kQuestion]; XCTAssertEqualObjects([answers[0] text], kAnswer); } - (void)testInitAlbert { - TFLBertQuestionAnswerer* albertAnswerer = [TFLBertQuestionAnswerer - questionAnswererWithModelPath:self.albertModelPath]; + TFLBertQuestionAnswerer* albertAnswerer = + [TFLBertQuestionAnswerer questionAnswererWithModelPath:self.albertModelPath]; XCTAssertNotNil(albertAnswerer); - NSArray<TFLQAAnswer*>* answers = [albertAnswerer answerWithContext:kContext - question:kQuestion]; + NSArray<TFLQAAnswer*>* answers = + [albertAnswerer answerWithContext:kContext question:kQuestion]; + XCTAssertEqualObjects([answers[0] text], kAnswer); }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/BUILD index c17dbc8..bc6bc2c 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/BUILD
@@ -1,5 +1,5 @@ package( - default_visibility = ["//tensorflow_lite_support:__subpackages__"], + default_visibility = ["//tensorflow_lite_support:internal"], licenses = ["notice"], # Apache 2.0 ) @@ -20,7 +20,29 @@ "//tensorflow_lite_support/ios/task/processor:TFLClassificationOptions", "//tensorflow_lite_support/ios/task/processor:TFLClassificationOptionsHelpers", "//tensorflow_lite_support/ios/task/processor:TFLClassificationResult", - "//tensorflow_lite_support/ios/task/processor/utils:TFLClassificationUtils", + "//tensorflow_lite_support/ios/task/processor:TFLClassificationResultHelpers", + "//tensorflow_lite_support/ios/task/vision/utils:GMLImageUtils", + ], +) + +objc_library( + name = "TFLObjectDetector", + srcs = [ + "sources/TFLObjectDetector.m", + ], + hdrs = [ + "sources/TFLObjectDetector.h", + ], + module_name = "TFLObjectDetector", + deps = [ + "//tensorflow_lite_support/c/task/vision:object_detector", + "//tensorflow_lite_support/ios:TFLCommonUtils", + "//tensorflow_lite_support/ios/task/core:TFLBaseOptions", + "//tensorflow_lite_support/ios/task/core:TFLBaseOptionsHelpers", + "//tensorflow_lite_support/ios/task/processor:TFLClassificationOptions", + "//tensorflow_lite_support/ios/task/processor:TFLClassificationOptionsHelpers", + "//tensorflow_lite_support/ios/task/processor:TFLDetectionResult", + "//tensorflow_lite_support/ios/task/processor:TFLDetectionResultHelpers", "//tensorflow_lite_support/ios/task/vision/utils:GMLImageUtils", ], )
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.h index 1b988f2b..1789508 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.h
@@ -14,10 +14,10 @@ ==============================================================================*/ #import <Foundation/Foundation.h> -#import "third_party/tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.h" -#import "third_party/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.h" -#import "third_party/tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h" -#import "third_party/tensorflow_lite_support/odml/ios/image/apis/GMLImage.h" +#import "tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult.h" +#import "tensorflow_lite_support/odml/ios/image/apis/GMLImage.h" NS_ASSUME_NONNULL_BEGIN
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.m index 06d6793..f91ed1b2 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.m
@@ -17,14 +17,14 @@ #import "tensorflow_lite_support/ios/sources/TFLCommonUtils.h" #import "tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.h" #import "tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.h" -#import "tensorflow_lite_support/ios/task/processor/utils/sources/TFLClassificationUtils.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLClassificationResult+Helpers.h" #import "tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.h" #include "tensorflow_lite_support/c/task/vision/image_classifier.h" @interface TFLImageClassifier () /** ImageClassifier backed by C API */ -@property(nonatomic) TfLiteImageClassifier* imageClassifier; +@property(nonatomic) TfLiteImageClassifier *imageClassifier; @end @implementation TFLImageClassifierOptions @@ -40,7 +40,7 @@ return self; } -- (nullable instancetype)initWithModelPath:(nonnull NSString*)modelPath { +- (nullable instancetype)initWithModelPath:(nonnull NSString *)modelPath { self = [self init]; if (self) { self.baseOptions.modelFile.filePath = modelPath; @@ -55,8 +55,7 @@ TfLiteImageClassifierDelete(_imageClassifier); } -- (instancetype)initWithImageClassifier: - (TfLiteImageClassifier*)imageClassifier { +- (instancetype)initWithImageClassifier:(TfLiteImageClassifier *)imageClassifier { self = [super init]; if (self) { _imageClassifier = imageClassifier; @@ -64,28 +63,27 @@ return self; } -+ (nullable instancetype)imageClassifierWithOptions: - (nonnull TFLImageClassifierOptions*)options - error:(NSError**)error { ++ (nullable instancetype)imageClassifierWithOptions:(nonnull TFLImageClassifierOptions *)options + error:(NSError **)error { TfLiteImageClassifierOptions cOptions = TfLiteImageClassifierOptionsCreate(); if (![options.classificationOptions - copyClassificationOptionsToCClassificationOptions: - &(cOptions.classification_options) - error:error]) + copyToCOptions:&(cOptions.classification_options) + error:error]) return nil; - [options.baseOptions copyBaseOptionsToCBaseOptions:&(cOptions.base_options)]; + [options.baseOptions copyToCOptions:&(cOptions.base_options)]; - TfLiteSupportError* createClassifierError = nil; - TfLiteImageClassifier* imageClassifier = + TfLiteSupportError *createClassifierError = nil; + TfLiteImageClassifier *imageClassifier = TfLiteImageClassifierFromOptions(&cOptions, &createClassifierError); - [options.classificationOptions deleteCStringArraysOfClassificationOptions: - &(cOptions.classification_options)]; + [options.classificationOptions + deleteCStringArraysOfClassificationOptions:&(cOptions.classification_options)]; if (!imageClassifier) { - [TFLCommonUtils errorFromTfLiteSupportError:createClassifierError - error:error]; + if (error) { + *error = [TFLCommonUtils errorWithCError:createClassifierError]; + } TfLiteSupportErrorDelete(createClassifierError); return nil; } @@ -93,20 +91,17 @@ return [[TFLImageClassifier alloc] initWithImageClassifier:imageClassifier]; } -- (nullable TFLClassificationResult*)classifyWithGMLImage:(GMLImage*)image - error:(NSError* _Nullable*) - error { +- (nullable TFLClassificationResult *)classifyWithGMLImage:(GMLImage *)image + error:(NSError *_Nullable *)error { return [self classifyWithGMLImage:image regionOfInterest:CGRectMake(0, 0, image.width, image.height) error:error]; } -- (nullable TFLClassificationResult*)classifyWithGMLImage:(GMLImage*)image - regionOfInterest:(CGRect)roi - error:(NSError* _Nullable*) - error { - TfLiteFrameBuffer* cFrameBuffer = - [GMLImageUtils cFrameBufferFromGMLImage:image error:error]; +- (nullable TFLClassificationResult *)classifyWithGMLImage:(GMLImage *)image + regionOfInterest:(CGRect)roi + error:(NSError *_Nullable *)error { + TfLiteFrameBuffer *cFrameBuffer = [GMLImageUtils cFrameBufferWithGMLImage:image error:error]; if (!cFrameBuffer) { return nil; @@ -117,10 +112,9 @@ .width = roi.size.width, .height = roi.size.height}; - TfLiteSupportError* classifyError = nil; - TfLiteClassificationResult* cClassificationResult = - TfLiteImageClassifierClassifyWithRoi(_imageClassifier, cFrameBuffer, - &boundingBox, &classifyError); + TfLiteSupportError *classifyError = nil; + TfLiteClassificationResult *cClassificationResult = TfLiteImageClassifierClassifyWithRoi( + _imageClassifier, cFrameBuffer, &boundingBox, &classifyError); free(cFrameBuffer->buffer); cFrameBuffer->buffer = nil; @@ -129,13 +123,15 @@ cFrameBuffer = nil; if (!cClassificationResult) { - [TFLCommonUtils errorFromTfLiteSupportError:classifyError error:error]; + if (error) { + *error = [TFLCommonUtils errorWithCError:classifyError]; + } TfLiteSupportErrorDelete(classifyError); return nil; } - TFLClassificationResult* classificationHeadsResults = [TFLClassificationUtils - classificationResultFromCClassificationResults:cClassificationResult]; + TFLClassificationResult *classificationHeadsResults = + [TFLClassificationResult classificationResultWithCResult:cClassificationResult]; TfLiteClassificationResultDelete(cClassificationResult); return classificationHeadsResults;
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.h new file mode 100644 index 0000000..38b3b0a --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.h
@@ -0,0 +1,92 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#import <Foundation/Foundation.h> +#import "tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult.h" +#import "tensorflow_lite_support/odml/ios/image/apis/GMLImage.h" + +NS_ASSUME_NONNULL_BEGIN + +/** + * Options to configure TFLObjectDetector. + */ +@interface TFLObjectDetectorOptions : NSObject + +/** + * Base options that is used for creation of any type of task. + * @seealso TFLBaseOptions + */ +@property(nonatomic, copy) TFLBaseOptions* baseOptions; + +/** + * Options that configure the display and filtering of results. + * @seealso TFLClassificationOptions + */ +@property(nonatomic, copy) TFLClassificationOptions* classificationOptions; + +/** + * Initializes TFLObjectDetectorOptions with the model path set to the specified + * path to a model file. + * @description The external model file, must be a single standalone TFLite + * file. It could be packed with TFLite Model Metadata[1] and associated files + * if exist. Fail to provide the necessary metadata and associated files might + * result in errors. Check the [documentation] + * (https://www.tensorflow.org/lite/convert/metadata) for each task about the + * specific requirement. + * + * @param modelPath Path to a TFLite model file. + * @return An instance of TFLObjectDetectorOptions set to the specified + * modelPath. + */ +- (nullable instancetype)initWithModelPath:(nonnull NSString*)modelPath; + +@end + +@interface TFLObjectDetector : NSObject + +/** + * Creates TFLObjectDetector from a model file and specified options . + * + * @param options TFLObjectDetectorOptions instance with the necessary + * properties set. + * + * @return A TFLObjectDetector instance. + */ ++ (nullable instancetype)objectDetectorWithOptions: + (nonnull TFLObjectDetectorOptions*)options + error:(NSError**)error + NS_SWIFT_NAME(objectDetector(options:)); + +/** + * Performs object detection on a GMLImage input, returns the detected objects + * in the image. + * + * @param image input to the model. + * @return Detection Result of type TFLDetectionResult an array of + * detected objeects where each detected object has a bounding box and an array + * of TFLCategory holding the predicted classes for the detected object. + */ +- (nullable TFLDetectionResult*)detectWithGMLImage:(GMLImage*)image + error:(NSError* _Nullable*)error + NS_SWIFT_NAME(detect(gmlImage:)); + +- (instancetype)init NS_UNAVAILABLE; + ++ (instancetype)new NS_UNAVAILABLE; + +@end + +NS_ASSUME_NONNULL_END
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.m new file mode 100644 index 0000000..345d710 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.m
@@ -0,0 +1,127 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#import "tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.h" +#import "tensorflow_lite_support/ios/sources/TFLCommon.h" +#import "tensorflow_lite_support/ios/sources/TFLCommonUtils.h" +#import "tensorflow_lite_support/ios/task/core/sources/TFLBaseOptions+Helpers.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLClassificationOptions+Helpers.h" +#import "tensorflow_lite_support/ios/task/processor/sources/TFLDetectionResult+Helpers.h" +#import "tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.h" + +#include "tensorflow_lite_support/c/task/vision/object_detector.h" + +@interface TFLObjectDetector () +/** ObjectDetector backed by C API */ +@property(nonatomic) TfLiteObjectDetector *objectDetector; +@end + +@implementation TFLObjectDetectorOptions +@synthesize baseOptions; +@synthesize classificationOptions; + +- (instancetype)init { + self = [super init]; + if (self) { + self.baseOptions = [[TFLBaseOptions alloc] init]; + self.classificationOptions = [[TFLClassificationOptions alloc] init]; + } + return self; +} + +- (nullable instancetype)initWithModelPath:(nonnull NSString *)modelPath { + self = [self init]; + if (self) { + self.baseOptions.modelFile.filePath = modelPath; + } + return self; +} + +@end + +@implementation TFLObjectDetector +- (void)dealloc { + TfLiteObjectDetectorDelete(_objectDetector); +} + +- (instancetype)initWithObjectDetector:(TfLiteObjectDetector *)objectDetector { + self = [super init]; + if (self) { + _objectDetector = objectDetector; + } + return self; +} + ++ (nullable instancetype)objectDetectorWithOptions:(nonnull TFLObjectDetectorOptions *)options + error:(NSError **)error { + TfLiteObjectDetectorOptions cOptions = TfLiteObjectDetectorOptionsCreate(); + if (![options.classificationOptions + copyToCOptions:&(cOptions.classification_options) + error:error]) + return nil; + + [options.baseOptions copyToCOptions:&(cOptions.base_options)]; + + TfLiteSupportError *createObjectDetectorError = nil; + TfLiteObjectDetector *objectDetector = + TfLiteObjectDetectorFromOptions(&cOptions, &createObjectDetectorError); + + [options.classificationOptions + deleteCStringArraysOfClassificationOptions:&(cOptions.classification_options)]; + + if (!objectDetector) { + if (error) { + *error = [TFLCommonUtils errorWithCError:createObjectDetectorError]; + } + TfLiteSupportErrorDelete(createObjectDetectorError); + return nil; + } + + return [[TFLObjectDetector alloc] initWithObjectDetector:objectDetector]; +} + +- (nullable TFLDetectionResult *)detectWithGMLImage:(GMLImage *)image + error:(NSError *_Nullable *)error { + TfLiteFrameBuffer *cFrameBuffer = [GMLImageUtils cFrameBufferWithGMLImage:image error:error]; + + if (!cFrameBuffer) { + return nil; + } + + TfLiteSupportError *detectError = nil; + TfLiteDetectionResult *cDetectionResult = + TfLiteObjectDetectorDetect(_objectDetector, cFrameBuffer, &detectError); + + free(cFrameBuffer->buffer); + cFrameBuffer->buffer = nil; + + free(cFrameBuffer); + cFrameBuffer = nil; + + if (!cDetectionResult) { + if (error) { + *error = [TFLCommonUtils errorWithCError:detectError]; + } + TfLiteSupportErrorDelete(detectError); + return nil; + } + + TFLDetectionResult *detectionResult = + [TFLDetectionResult detectionResultWithCResult:cDetectionResult]; + TfLiteDetectionResultDelete(cDetectionResult); + + return detectionResult; +} + +@end
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.h index 298485b..8c36e0e 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.h
@@ -15,7 +15,7 @@ #import <Foundation/Foundation.h> #include "tensorflow_lite_support/c/task/vision/core/frame_buffer.h" -#import "third_party/tensorflow_lite_support/odml/ios/image/apis/GMLImage.h" +#import "tensorflow_lite_support/odml/ios/image/apis/GMLImage.h" NS_ASSUME_NONNULL_BEGIN @@ -37,7 +37,7 @@ * @return The TfLiteFrameBuffer created from the gmlImage which can be used * with the TF Lite Task Vision C library. */ -+ (nullable TfLiteFrameBuffer*)cFrameBufferFromGMLImage:(GMLImage*)gmlImage ++ (nullable TfLiteFrameBuffer*)cFrameBufferWithGMLImage:(GMLImage*)gmlImage error:(NSError* _Nullable*) error;
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.m index 72425b3..373a476 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.m
@@ -24,20 +24,18 @@ #import <CoreVideo/CoreVideo.h> @interface TFLCVPixelBufferUtils : NSObject -+ (uint8_t* _Nullable) - convertBGRAtoRGBforPixelBufferBaseAddress:(CVPixelBufferRef)pixelBuffer - error:(NSError**)error; ++ (uint8_t *_Nullable)convertBGRAtoRGBforPixelBufferBaseAddress:(CVPixelBufferRef)pixelBuffer + error:(NSError **)error; @end @interface UIImage (RawPixelDataUtils) -- (TfLiteFrameBuffer*)frameBufferWithError:(NSError**)error; +- (TfLiteFrameBuffer *)frameBufferWithError:(NSError **)error; @end @implementation TFLCVPixelBufferUtils -+ (uint8_t*)convertBGRAtoRGBforPixelBufferBaseAddress: - (CVPixelBufferRef)pixelBuffer - error:(NSError**)error { ++ (uint8_t *)convertBGRAtoRGBforPixelBufferBaseAddress:(CVPixelBufferRef)pixelBuffer + error:(NSError **)error { size_t width = CVPixelBufferGetWidth(pixelBuffer); size_t height = CVPixelBufferGetHeight(pixelBuffer); size_t stride = CVPixelBufferGetBytesPerRow(pixelBuffer); @@ -45,21 +43,17 @@ int destinationChannelCount = 3; size_t destinationBytesPerRow = destinationChannelCount * width; - uint8_t* pixelBufferBaseAddress = - (uint8_t*)CVPixelBufferGetBaseAddress(pixelBuffer); + uint8_t *pixelBufferBaseAddress = (uint8_t *)CVPixelBufferGetBaseAddress(pixelBuffer); - uint8_t* destPixelBufferAddress = - [TFLCommonUtils mallocWithSize:height * destinationBytesPerRow - error:error]; + uint8_t *destPixelBufferAddress = [TFLCommonUtils mallocWithSize:height * destinationBytesPerRow + error:error]; if (!destPixelBufferAddress) { return NULL; } - vImage_Buffer srcBuffer = {.data = pixelBufferBaseAddress, - .height = height, - .width = width, - .rowBytes = stride}; + vImage_Buffer srcBuffer = { + .data = pixelBufferBaseAddress, .height = height, .width = width, .rowBytes = stride}; vImage_Buffer destBuffer = {.data = destPixelBufferAddress, .height = height, @@ -67,13 +61,13 @@ .rowBytes = destinationBytesPerRow}; vImage_Error convertError = kvImageNoError; - convertError = - vImageConvert_BGRA8888toRGB888(&srcBuffer, &destBuffer, kvImageNoFlags); + convertError = vImageConvert_BGRA8888toRGB888(&srcBuffer, &destBuffer, kvImageNoFlags); if (convertError != kvImageNoError) { - [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeImageProcessingError - description:@"Image format conversion failed." - error:error]; + if (error) { + *error = [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeImageProcessingError + description:@"Image format conversion failed."]; + } return NULL; } @@ -85,49 +79,45 @@ @implementation UIImage (RawPixelDataUtils) -- (TfLiteFrameBuffer*)frameBufferWithError:(NSError**)error { - TfLiteFrameBuffer* frameBuffer = NULL; +- (TfLiteFrameBuffer *)frameBufferWithError:(NSError **)error { + TfLiteFrameBuffer *frameBuffer = NULL; if (self.CGImage) { frameBuffer = [self frameBufferFromCGImage:self.CGImage error:error]; } else if (self.CIImage) { frameBuffer = [self frameBufferFromCIImage:self.CIImage error:error]; - } else { - [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError - description:@"UIImage should be initialized from" - " CIImage or CGImage." - error:error]; + } else if (error) { + *error = [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError + description:@"UIImage should be initialized from" + " CIImage or CGImage."]; } return frameBuffer; } -+ (UInt8* _Nullable)pixelDataFromCGImage:(CGImageRef)cgImage - error:(NSError**)error { ++ (UInt8 *_Nullable)pixelDataFromCGImage:(CGImageRef)cgImage error:(NSError **)error { long width = CGImageGetWidth(cgImage); long height = CGImageGetHeight(cgImage); int bitsPerComponent = 8; - UInt8* buffer_to_return = NULL; + UInt8 *buffer_to_return = NULL; CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - CGContextRef context = - CGBitmapContextCreate(nil, width, height, bitsPerComponent, 0, colorSpace, - kCGImageAlphaNoneSkipLast); + CGContextRef context = CGBitmapContextCreate(nil, width, height, bitsPerComponent, 0, colorSpace, + kCGImageAlphaNoneSkipLast); if (context) { CGContextDrawImage(context, CGRectMake(0, 0, width, height), cgImage); - buffer_to_return = [UIImage - populateRGBBufferFromSourceRGBABuffer:CGBitmapContextGetData(context) - width:width - height:height]; + buffer_to_return = + [UIImage populateRGBBufferFromSourceRGBABuffer:CGBitmapContextGetData(context) + width:width + height:height]; CGContextRelease(context); } - if (buffer_to_return == NULL) { - [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeImageProcessingError - description:@"Image format conversion failed." - error:error]; + if ((buffer_to_return == NULL) && (error)) { + *error = [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeImageProcessingError + description:@"Image format conversion failed."]; } CGColorSpaceRelease(colorSpace); @@ -135,16 +125,15 @@ return buffer_to_return; } -+ (nullable UInt8*)populateRGBBufferFromSourceRGBABuffer:(UInt8*)buffer - width:(size_t)width - height:(size_t)height { - if (!buffer) - return nil; ++ (nullable UInt8 *)populateRGBBufferFromSourceRGBABuffer:(UInt8 *)buffer + width:(size_t)width + height:(size_t)height { + if (!buffer) return nil; int sourceChannelCount = 4; int destChannelCount = 3; - UInt8* buffer_to_return = malloc(height * destChannelCount * width); + UInt8 *buffer_to_return = malloc(height * destChannelCount * width); if (!buffer_to_return) { return nil; } @@ -160,15 +149,14 @@ return buffer_to_return; } -- (TfLiteFrameBuffer*)frameBufferFromCGImage:(CGImageRef)cgImage - error:(NSError**)error { - UInt8* buffer = [UIImage pixelDataFromCGImage:cgImage error:error]; +- (TfLiteFrameBuffer *)frameBufferFromCGImage:(CGImageRef)cgImage error:(NSError **)error { + UInt8 *buffer = [UIImage pixelDataFromCGImage:cgImage error:error]; if (buffer == NULL) { return NULL; } - TfLiteFrameBuffer* cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); + TfLiteFrameBuffer *cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); cFrameBuffer->dimension.width = (int)CGImageGetWidth(cgImage); cFrameBuffer->dimension.height = (int)CGImageGetHeight(cgImage); @@ -180,16 +168,14 @@ return cFrameBuffer; } -- (TfLiteFrameBuffer*)frameBufferFromCIImage:(CIImage*)ciImage - error:(NSError**)error { - uint8_t* buffer = nil; +- (TfLiteFrameBuffer *)frameBufferFromCIImage:(CIImage *)ciImage error:(NSError **)error { + uint8_t *buffer = nil; int width = 0; int height = 0; if (ciImage.pixelBuffer) { - buffer = [TFLCVPixelBufferUtils - convertBGRAtoRGBforPixelBufferBaseAddress:ciImage.pixelBuffer - error:error]; + buffer = [TFLCVPixelBufferUtils convertBGRAtoRGBforPixelBufferBaseAddress:ciImage.pixelBuffer + error:error]; width = (int)CVPixelBufferGetWidth(ciImage.pixelBuffer); height = (int)CVPixelBufferGetHeight(ciImage.pixelBuffer); @@ -197,18 +183,17 @@ buffer = [UIImage pixelDataFromCGImage:ciImage.CGImage error:error]; width = (int)CGImageGetWidth(ciImage.CGImage); height = (int)CGImageGetWidth(ciImage.CGImage); - } else { - [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError - description:@"CIImage should have CGImage or " - "CVPixelBuffer info." - error:error]; + } else if (error) { + *error = [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError + description:@"CIImage should have CGImage or " + "CVPixelBuffer info."]; } if (buffer == NULL) { return NULL; } - TfLiteFrameBuffer* cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); + TfLiteFrameBuffer *cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); cFrameBuffer->buffer = buffer; cFrameBuffer->dimension.width = width; cFrameBuffer->dimension.height = height; @@ -223,49 +208,42 @@ @implementation GMLImageUtils -+ (nullable TfLiteFrameBuffer*)cFrameBufferFromGMLImage:(GMLImage*)gmlImage - error:(NSError* _Nullable*) - error { - TfLiteFrameBuffer* cFrameBuffer = NULL; ++ (nullable TfLiteFrameBuffer *)cFrameBufferWithGMLImage:(GMLImage *)gmlImage + error:(NSError *_Nullable *)error { + TfLiteFrameBuffer *cFrameBuffer = NULL; switch (gmlImage.imageSourceType) { case GMLImageSourceTypeSampleBuffer: { - CVPixelBufferRef sampleImagePixelBuffer = - CMSampleBufferGetImageBuffer(gmlImage.sampleBuffer); - cFrameBuffer = - [GMLImageUtils bufferFromCVPixelBuffer:sampleImagePixelBuffer - error:error]; + CVPixelBufferRef sampleImagePixelBuffer = CMSampleBufferGetImageBuffer(gmlImage.sampleBuffer); + cFrameBuffer = [GMLImageUtils bufferFromCVPixelBuffer:sampleImagePixelBuffer error:error]; break; } case GMLImageSourceTypePixelBuffer: { - cFrameBuffer = [GMLImageUtils bufferFromCVPixelBuffer:gmlImage.pixelBuffer - error:error]; + cFrameBuffer = [GMLImageUtils bufferFromCVPixelBuffer:gmlImage.pixelBuffer error:error]; break; } case GMLImageSourceTypeImage: { - cFrameBuffer = [GMLImageUtils frameBufferFromUIImage:gmlImage.image - error:error]; + cFrameBuffer = [GMLImageUtils frameBufferFromUIImage:gmlImage.image error:error]; } default: - [TFLCommonUtils - customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError - description:@"Invalid source type for GMLImage." - error:error]; + if (error) { + *error = [TFLCommonUtils customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError + description:@"Invalid source type for GMLImage."]; + } break; } return cFrameBuffer; } -+ (TfLiteFrameBuffer*)frameBufferFromUIImage:(UIImage*)image - error:(NSError**)error { ++ (TfLiteFrameBuffer *)frameBufferFromUIImage:(UIImage *)image error:(NSError **)error { return [image frameBufferWithError:error]; } -+ (TfLiteFrameBuffer*)bufferFromCVPixelBuffer:(CVPixelBufferRef)pixelBuffer - error:(NSError**)error { - uint8_t* buffer = nil; ++ (TfLiteFrameBuffer *)bufferFromCVPixelBuffer:(CVPixelBufferRef)pixelBuffer + error:(NSError **)error { + uint8_t *buffer = nil; enum TfLiteFrameBufferFormat cPixelFormat = kRGB; CVPixelBufferLockBaseAddress(pixelBuffer, 0); @@ -274,30 +252,27 @@ switch (pixelBufferFormat) { case kCVPixelFormatType_24RGB: { cPixelFormat = kRGB; - buffer = [GMLImageUtils copyPixelufferDataForInference:pixelBuffer - error:error]; + buffer = [GMLImageUtils copyPixelufferDataForInference:pixelBuffer error:error]; break; } case kCVPixelFormatType_32RGBA: { cPixelFormat = kRGBA; - buffer = [GMLImageUtils copyPixelufferDataForInference:pixelBuffer - error:error]; + buffer = [GMLImageUtils copyPixelufferDataForInference:pixelBuffer error:error]; break; } case kCVPixelFormatType_32BGRA: { cPixelFormat = kRGB; - buffer = [TFLCVPixelBufferUtils - convertBGRAtoRGBforPixelBufferBaseAddress:pixelBuffer - error:error]; + buffer = [TFLCVPixelBufferUtils convertBGRAtoRGBforPixelBufferBaseAddress:pixelBuffer + error:error]; break; } default: { - [TFLCommonUtils - customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError - description: - @"Unsupported pixel format for TfLiteFrameBufferFormat." - error:error]; + if (error) { + *error = [TFLCommonUtils + customErrorWithCode:TFLSupportErrorCodeInvalidArgumentError + description:@"Unsupported pixel format for TfLiteFrameBufferFormat."]; + } break; } } @@ -308,7 +283,7 @@ return nil; } - TfLiteFrameBuffer* cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); + TfLiteFrameBuffer *cFrameBuffer = malloc(sizeof(TfLiteFrameBuffer)); cFrameBuffer->dimension.width = (int)CVPixelBufferGetWidth(pixelBuffer); cFrameBuffer->dimension.height = (int)CVPixelBufferGetHeight(pixelBuffer); @@ -318,14 +293,12 @@ return cFrameBuffer; } -+ (UInt8*)copyPixelufferDataForInference:(CVPixelBufferRef)pixelBuffer - error:(NSError**)error { ++ (UInt8 *)copyPixelufferDataForInference:(CVPixelBufferRef)pixelBuffer error:(NSError **)error { size_t height = CVPixelBufferGetHeight(pixelBuffer); size_t stride = CVPixelBufferGetBytesPerRow(pixelBuffer); - UInt8* buffer = [TFLCommonUtils mallocWithSize:height * stride error:error]; + UInt8 *buffer = [TFLCommonUtils mallocWithSize:height * stride error:error]; - if (buffer) - memcpy(buffer, CVPixelBufferGetBaseAddress(pixelBuffer), height * stride); + if (buffer) memcpy(buffer, CVPixelBufferGetBaseAddress(pixelBuffer), height * stride); return buffer; }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/BUILD index 6ae128e1..5a2c8b7 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/BUILD
@@ -4,7 +4,7 @@ load("@org_tensorflow//tensorflow/lite:special_rules.bzl", "tflite_ios_lab_runner") package( - default_visibility = ["//tensorflow_lite_support:__subpackages__"], + default_visibility = ["//visibility:private"], licenses = ["notice"], # Apache 2.0 ) @@ -19,6 +19,7 @@ tags = TFL_DEFAULT_TAGS, deps = [ "//tensorflow_lite_support/ios/task/vision:TFLImageClassifier", + "//tensorflow_lite_support/ios/test/task/vision/utils:GMLImageHelpers", ], ) @@ -43,6 +44,7 @@ tags = TFL_DEFAULT_TAGS, deps = [ "//tensorflow_lite_support/ios/task/vision:TFLImageClassifier", + "//tensorflow_lite_support/ios/test/task/vision/utils:GMLImageHelpers", ], ) @@ -55,3 +57,32 @@ ":TFLImageClassifierObjcTestLibrary", ], ) + +objc_library( + name = "TFLImageClassifierCoreMLDelegateTestLibrary", + testonly = 1, + srcs = ["TFLImageClassifierCoreMLDelegateTest.mm"], + data = [ + "//tensorflow_lite_support/cc/test/testdata/task/vision:test_images", + "//tensorflow_lite_support/cc/test/testdata/task/vision:test_models", + ], + tags = TFL_DEFAULT_TAGS, + deps = [ + "//tensorflow_lite_support/c/task/vision/utils:frame_buffer_cpp_c_utils", + "//tensorflow_lite_support/cc/task/vision:image_classifier", + "//tensorflow_lite_support/ios/task/vision/utils:GMLImageUtils", + "//tensorflow_lite_support/ios/test/task/vision/utils:GMLImageHelpers", + "//third_party/apple_frameworks:XCTest", + "@org_tensorflow//tensorflow/lite/experimental/acceleration/configuration:coreml_plugin", + ], +) + +ios_unit_test( + name = "TFLImageClassifierCoreMLDelegateTest", + minimum_os_version = TFL_MINIMUM_OS_VERSION, + runner = tflite_ios_lab_runner("IOS_LATEST"), + tags = TFL_DEFAULT_TAGS + TFL_DISABLED_SANITIZER_TAGS, + deps = [ + ":TFLImageClassifierCoreMLDelegateTestLibrary", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierCoreMLDelegateTest.mm b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierCoreMLDelegateTest.mm new file mode 100644 index 0000000..eb0e1d84 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierCoreMLDelegateTest.mm
@@ -0,0 +1,99 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +==============================================================================*/ +#import <XCTest/XCTest.h> + +#import "third_party/tensorflow_lite_support/ios/task/vision/utils/sources/GMLImageUtils.h" +#import "third_party/tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.h" + +#include "third_party/tensorflow_lite_support/c/task/vision/utils/frame_buffer_cpp_c_utils.h" +#include "third_party/tensorflow_lite_support/cc/task/vision/image_classifier.h" + +using ImageClassifier = ::tflite::task::vision::ImageClassifier; +using ImageClassifierOptions = ::tflite::task::vision::ImageClassifierOptions; +using ClassificationResult = ::tflite::task::vision::ClassificationResult; + +@interface TFLImageClassifierCoreMLDelegateTest : XCTestCase { + NSString* _modelPath; +} +@end + +@implementation TFLImageClassifierCoreMLDelegateTest + +- (void)setUp { + [super setUp]; + + // This image classifier can mostly be deoplyed through CoreML. Below is from the delegate logs: + // "INFO: CoreML delegate: 64 nodes delegated out of 66 nodes, with 2 partitions." + _modelPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"mobilenet_v2_1.0_224" + ofType:@"tflite"]; + XCTAssertNotNil(_modelPath); +} + +- (void)testCoreMLDelegateCreationFailsWithNeuralEngine { + // Configures the options. + ImageClassifierOptions options; + options.mutable_base_options()->mutable_model_file()->set_file_name(_modelPath.UTF8String); + options.mutable_base_options() + ->mutable_compute_settings() + ->mutable_tflite_settings() + ->set_delegate(::acceleration::Delegate::CORE_ML); + options.mutable_base_options() + ->mutable_compute_settings() + ->mutable_tflite_settings() + ->mutable_coreml_settings() + ->set_enabled_devices(::acceleration::CoreMLDelegateSettings::DEVICES_ALL); + + // Creates the classifier. + tflite::support::StatusOr<std::unique_ptr<ImageClassifier>> image_classifier_status = + ImageClassifier::CreateFromOptions(options); + XCTAssertTrue(image_classifier_status.ok()); + const std::unique_ptr<ImageClassifier>& image_classifier = image_classifier_status.value(); + XCTAssertNotEqual(image_classifier.get(), nullptr); + + // Loads the test image. + GMLImage* gmlImage = [GMLImage imageFromBundleWithClass:[self class] + fileName:@"burger" + ofType:@"jpg"]; + XCTAssertNotNil(gmlImage); + + // Converts the test image to a frame buffer. + NSError* error; + TfLiteFrameBuffer* cFrameBuffer = [GMLImageUtils cFrameBufferWithGMLImage:gmlImage error:&error]; + XCTAssertNotEqual(cFrameBuffer, nullptr); + tflite::support::StatusOr<std::unique_ptr<::tflite::task::vision::FrameBuffer>> + frame_buffer_status = ::tflite::task::vision::CreateCppFrameBuffer(cFrameBuffer); + XCTAssertTrue(frame_buffer_status.ok()); + const ::tflite::task::vision::FrameBuffer& frame_buffer = *frame_buffer_status.value(); + + // Classifies the image. + tflite::support::StatusOr<ClassificationResult> classification_result_status = + image_classifier->Classify(frame_buffer); + XCTAssertTrue(classification_result_status.ok()); + const ClassificationResult& classification_result = classification_result_status.value(); + + // Retrieves the top class. + XCTAssertGreaterThan(classification_result.classifications_size(), 0); + const ::tflite::task::vision::Classifications& classification = + classification_result.classifications(0); + XCTAssertGreaterThan(classification.classes_size(), 0); + const ::tflite::task::vision::Class& topClass = classification.classes(0); + + // Verifies the class name & score. + NSString* className = [NSString stringWithCString:topClass.class_name().c_str()]; + XCTAssertEqualObjects(className, @"cheeseburger"); + XCTAssertEqualWithAccuracy(topClass.score(), 0.748976, 0.001); +} + +@end
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.m index f269594..642c2cc 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.m
@@ -13,145 +13,127 @@ limitations under the License. ==============================================================================*/ #import <XCTest/XCTest.h> + #import "tensorflow_lite_support/ios/task/vision/sources/TFLImageClassifier.h" +#import "tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.h" NS_ASSUME_NONNULL_BEGIN @interface TFLImageClassifierTests : XCTestCase -@property(nonatomic, nullable) NSString* modelPath; +@property(nonatomic, nullable) NSString *modelPath; @end @implementation TFLImageClassifierTests -- (GMLImage*)imageFromBundleWithName:(NSString*)name ofType:(NSString*)type { - NSString* imagePath = - [[NSBundle bundleForClass:[self class]] pathForResource:name ofType:type]; - XCTAssertNotNil(imagePath); - UIImage* image = [[UIImage alloc] initWithContentsOfFile:imagePath]; - XCTAssertNotNil(image); - - GMLImage* gmlImage = [[GMLImage alloc] initWithImage:image]; - XCTAssertNotNil(gmlImage); - - return gmlImage; -} - (void)setUp { - // Put setup code here. This method is called before the invocation of each - // test method in the class. static let bundle = Bundle(for: - // TFLSentencepieceTokenizerTest.self) - self.modelPath = [[NSBundle bundleForClass:[self class]] - pathForResource:@"mobilenet_v2_1.0_224" - ofType:@"tflite"]; + // Put setup code here. This method is called before the invocation of each test method in the + // class. + [super setUp]; + self.modelPath = [[NSBundle bundleForClass:[self class]] pathForResource:@"mobilenet_v2_1.0_224" + ofType:@"tflite"]; XCTAssertNotNil(self.modelPath); } -- (void)tearDown { - // Put teardown code here. This method is called after the invocation of each - // test method in the class. -} - - (void)testSuccessfullImageInferenceOnMLImageWithUIImage { - TFLImageClassifierOptions* imageClassifierOptions = + TFLImageClassifierOptions *imageClassifierOptions = [[TFLImageClassifierOptions alloc] initWithModelPath:self.modelPath]; - TFLImageClassifier* imageClassifier = - [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions - error:nil]; + TFLImageClassifier *imageClassifier = + [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions error:nil]; XCTAssertNotNil(imageClassifier); - GMLImage* gmlImage = [self imageFromBundleWithName:@"burger" ofType:@"jpg"]; - TFLClassificationResult* classificationResults = - [imageClassifier classifyWithGMLImage:gmlImage error:nil]; + GMLImage *gmlImage = [GMLImage imageFromBundleWithClass:[self class] + fileName:@"burger" + ofType:@"jpg"]; + XCTAssertNotNil(gmlImage); + + TFLClassificationResult *classificationResults = [imageClassifier classifyWithGMLImage:gmlImage + error:nil]; XCTAssertTrue([classificationResults.classifications count] > 0); - XCTAssertTrue([classificationResults.classifications[0].categories count] > - 0); + XCTAssertTrue([classificationResults.classifications[0].categories count] > 0); - TFLCategory* category = - classificationResults.classifications[0].categories[0]; + TFLCategory *category = classificationResults.classifications[0].categories[0]; XCTAssertTrue([category.label isEqual:@"cheeseburger"]); // TODO: match the score as image_classifier_test.cc XCTAssertEqualWithAccuracy(category.score, 0.748976, 0.001); } - (void)testModelOptionsWithMaxResults { - TFLImageClassifierOptions* imageClassifierOptions = + TFLImageClassifierOptions *imageClassifierOptions = [[TFLImageClassifierOptions alloc] initWithModelPath:self.modelPath]; int maxResults = 3; imageClassifierOptions.classificationOptions.maxResults = maxResults; - TFLImageClassifier* imageClassifier = - [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions - error:nil]; + TFLImageClassifier *imageClassifier = + [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions error:nil]; XCTAssertNotNil(imageClassifier); - GMLImage* gmlImage = [self imageFromBundleWithName:@"burger" ofType:@"jpg"]; + GMLImage *gmlImage = [GMLImage imageFromBundleWithClass:[self class] + fileName:@"burger" + ofType:@"jpg"]; + XCTAssertNotNil(gmlImage); - TFLClassificationResult* classificationResults = - [imageClassifier classifyWithGMLImage:gmlImage error:nil]; + TFLClassificationResult *classificationResults = [imageClassifier classifyWithGMLImage:gmlImage + error:nil]; XCTAssertTrue([classificationResults.classifications count] > 0); - XCTAssertLessThanOrEqual( - [classificationResults.classifications[0].categories count], maxResults); + XCTAssertLessThanOrEqual([classificationResults.classifications[0].categories count], maxResults); - TFLCategory* category = - classificationResults.classifications[0].categories[0]; + TFLCategory *category = classificationResults.classifications[0].categories[0]; XCTAssertTrue([category.label isEqual:@"cheeseburger"]); // TODO: match the score as image_classifier_test.cc XCTAssertEqualWithAccuracy(category.score, 0.748976, 0.001); } - (void)testInferenceWithBoundingBox { - TFLImageClassifierOptions* imageClassifierOptions = + TFLImageClassifierOptions *imageClassifierOptions = [[TFLImageClassifierOptions alloc] initWithModelPath:self.modelPath]; int maxResults = 3; imageClassifierOptions.classificationOptions.maxResults = maxResults; - TFLImageClassifier* imageClassifier = - [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions - error:nil]; + TFLImageClassifier *imageClassifier = + [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions error:nil]; XCTAssertNotNil(imageClassifier); - GMLImage* gmlImage = [self imageFromBundleWithName:@"multi_objects" - ofType:@"jpg"]; + GMLImage *gmlImage = [GMLImage imageFromBundleWithClass:[self class] + fileName:@"multi_objects" + ofType:@"jpg"]; + XCTAssertNotNil(gmlImage); CGRect roi = CGRectMake(406, 110, 148, 153); - TFLClassificationResult* classificationResults = - [imageClassifier classifyWithGMLImage:gmlImage - regionOfInterest:roi - error:nil]; + TFLClassificationResult *classificationResults = [imageClassifier classifyWithGMLImage:gmlImage + regionOfInterest:roi + error:nil]; XCTAssertTrue([classificationResults.classifications count] > 0); - XCTAssertTrue([classificationResults.classifications[0].categories count] > - 0); + XCTAssertTrue([classificationResults.classifications[0].categories count] > 0); - TFLCategory* category = - classificationResults.classifications[0].categories[0]; + TFLCategory *category = classificationResults.classifications[0].categories[0]; // TODO: match the label and score as image_classifier_test.cc // XCTAssertTrue([category.label isEqual:@"soccer ball"]); // XCTAssertEqualWithAccuracy(category.score, 0.256512, 0.001); } - (void)testInferenceWithRGBAImage { - TFLImageClassifierOptions* imageClassifierOptions = + TFLImageClassifierOptions *imageClassifierOptions = [[TFLImageClassifierOptions alloc] initWithModelPath:self.modelPath]; - TFLImageClassifier* imageClassifier = - [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions - error:nil]; + TFLImageClassifier *imageClassifier = + [TFLImageClassifier imageClassifierWithOptions:imageClassifierOptions error:nil]; XCTAssertNotNil(imageClassifier); - GMLImage* gmlImage = [self imageFromBundleWithName:@"sparrow" ofType:@"png"]; + GMLImage *gmlImage = [GMLImage imageFromBundleWithClass:[self class] + fileName:@"sparrow" + ofType:@"png"]; XCTAssertNotNil(gmlImage); - TFLClassificationResult* classificationResults = - [imageClassifier classifyWithGMLImage:gmlImage error:nil]; + TFLClassificationResult *classificationResults = [imageClassifier classifyWithGMLImage:gmlImage + error:nil]; XCTAssertTrue([classificationResults.classifications count] > 0); - XCTAssertTrue([classificationResults.classifications[0].categories count] > - 0); + XCTAssertTrue([classificationResults.classifications[0].categories count] > 0); - TFLCategory* category = - classificationResults.classifications[0].categories[0]; + TFLCategory *category = classificationResults.classifications[0].categories[0]; XCTAssertTrue([category.label isEqual:@"junco"]); - // TODO: inspect if score is correct. Better to test againest "burger", - // because we know the expected result for "burger.jpg". + // TODO: inspect if score is correct. Better to test againest "burger", because we know the + // expected result for "burger.jpg". XCTAssertEqualWithAccuracy(category.score, 0.253016, 0.001); }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.swift b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.swift index 0375168..a6087e79 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.swift +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/image_classifier/TFLImageClassifierTests.swift
@@ -12,6 +12,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ +import GMLImageHelpers import XCTest @testable import TFLImageClassifier @@ -33,7 +34,12 @@ let imageClassifier = try TFLImageClassifier.imageClassifier(options: imageClassifierOptions!) - let gmlImage = try gmlImage(withName: "burger", ofType: "jpg") + let gmlImage = try XCTUnwrap( + MLImage.imageFromBundle( + class: type(of: self), + filename: "burger", + type: "jpg")) + let classificationResults: TFLClassificationResult = try imageClassifier.classify(gmlImage: gmlImage) @@ -59,7 +65,11 @@ let imageClassifier = try TFLImageClassifier.imageClassifier(options: imageClassifierOptions!) - let gmlImage = try gmlImage(withName: "burger", ofType: "jpg") + let gmlImage = try XCTUnwrap( + MLImage.imageFromBundle( + class: type(of: self), + filename: "burger", + type: "jpg")) let classificationResults: TFLClassificationResult = try imageClassifier.classify( gmlImage: gmlImage) @@ -84,7 +94,11 @@ let imageClassifier = try TFLImageClassifier.imageClassifier(options: imageClassifierOptions!) - let gmlImage = try gmlImage(withName: "multi_objects", ofType: "jpg") + let gmlImage = try XCTUnwrap( + MLImage.imageFromBundle( + class: type(of: self), + filename: "multi_objects", + type: "jpg")) let roi = CGRect(x: 406, y: 110, width: 148, height: 153) let classificationResults = @@ -110,7 +124,11 @@ let imageClassifier = try TFLImageClassifier.imageClassifier(options: imageClassifierOptions!) - let gmlImage = try gmlImage(withName: "sparrow", ofType: "png") + let gmlImage = try XCTUnwrap( + MLImage.imageFromBundle( + class: type(of: self), + filename: "sparrow", + type: "png")) let classificationResults = try imageClassifier.classify(gmlImage: gmlImage) @@ -123,14 +141,4 @@ XCTAssertEqual(category.label, "junco") XCTAssertEqual(category.score, 0.253016, accuracy: 0.001) } - - private func gmlImage(withName name: String, ofType type: String) throws -> MLImage { - let imagePath = - try XCTUnwrap(TFLImageClassifierTests.bundle.path(forResource: name, ofType: type)) - let image = UIImage(contentsOfFile: imagePath) - let imageForInference = try XCTUnwrap(image) - let gmlImage = try XCTUnwrap(MLImage(image: imageForInference)) - - return gmlImage - } }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/object_detector/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/object_detector/BUILD new file mode 100644 index 0000000..4f0f8d1 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/object_detector/BUILD
@@ -0,0 +1,59 @@ +load("@build_bazel_rules_swift//swift:swift.bzl", "swift_library") +load("@org_tensorflow//tensorflow/lite/ios:ios.bzl", "TFL_DEFAULT_TAGS", "TFL_DISABLED_SANITIZER_TAGS", "TFL_MINIMUM_OS_VERSION") +load("@build_bazel_rules_apple//apple:ios.bzl", "ios_unit_test") +load("@org_tensorflow//tensorflow/lite:special_rules.bzl", "tflite_ios_lab_runner") + +package( + default_visibility = ["//visibility:private"], + licenses = ["notice"], # Apache 2.0 +) + +objc_library( + name = "TFLObjectDetectorObjcTestLibrary", + testonly = 1, + srcs = ["TFLObjectDetectorTests.m"], + data = [ + "//tensorflow_lite_support/cc/test/testdata/task/vision:test_images", + "//tensorflow_lite_support/cc/test/testdata/task/vision:test_models", + ], + tags = TFL_DEFAULT_TAGS, + deps = [ + "//tensorflow_lite_support/ios/task/vision:TFLObjectDetector", + "//tensorflow_lite_support/ios/test/task/vision/utils:GMLImageHelpers", + ], +) + +ios_unit_test( + name = "TFLObjectDetectorObjcTest", + minimum_os_version = TFL_MINIMUM_OS_VERSION, + runner = tflite_ios_lab_runner("IOS_LATEST"), + tags = TFL_DEFAULT_TAGS + TFL_DISABLED_SANITIZER_TAGS, + deps = [ + ":TFLObjectDetectorObjcTestLibrary", + ], +) + +swift_library( + name = "TFLObjectDetectorSwiftTestLibrary", + testonly = 1, + srcs = ["TFLObjectDetectorTests.swift"], + data = [ + "//tensorflow_lite_support/cc/test/testdata/task/vision:test_images", + "//tensorflow_lite_support/cc/test/testdata/task/vision:test_models", + ], + tags = TFL_DEFAULT_TAGS, + deps = [ + "//tensorflow_lite_support/ios/task/vision:TFLObjectDetector", + "//tensorflow_lite_support/ios/test/task/vision/utils:GMLImageHelpers", + ], +) + +ios_unit_test( + name = "TFLObjectDetectorSwiftTest", + minimum_os_version = TFL_MINIMUM_OS_VERSION, + runner = tflite_ios_lab_runner("IOS_LATEST"), + tags = TFL_DEFAULT_TAGS + TFL_DISABLED_SANITIZER_TAGS, + deps = [ + ":TFLObjectDetectorSwiftTestLibrary", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/object_detector/TFLObjectDetectorTests.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/object_detector/TFLObjectDetectorTests.m new file mode 100644 index 0000000..95518dc --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/object_detector/TFLObjectDetectorTests.m
@@ -0,0 +1,124 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#import <CoreGraphics/CoreGraphics.h> +#import <XCTest/XCTest.h> + +#import "tensorflow_lite_support/ios/task/vision/sources/TFLObjectDetector.h" +#import "tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.h" + +#define VerifyDetection(detection, expectedBoundingBox, expectedFirstScore, expectedFirstLabel) \ + XCTAssertGreaterThan([detection.categories count], 0); \ + NSLog(@"Detected %f", detection.categories[0].score); \ + NSLog(@"Expected %f", expectedFirstScore); \ + XCTAssertEqual(detection.boundingBox.origin.x, expectedBoundingBox.origin.x); \ + XCTAssertEqual(detection.boundingBox.origin.y, expectedBoundingBox.origin.y); \ + XCTAssertEqual(detection.boundingBox.size.width, expectedBoundingBox.size.width); \ + XCTAssertEqual(detection.boundingBox.size.height, expectedBoundingBox.size.height); \ + XCTAssertEqualObjects(detection.categories[0].label, expectedFirstLabel); \ + XCTAssertEqualWithAccuracy(detection.categories[0].score, expectedFirstScore, 0.001) + +@interface TFLObjectDetectorTests : XCTestCase +@property(nonatomic, nullable) NSString *modelPath; +@end + +@implementation TFLObjectDetectorTests + +- (void)setUp { + // Put setup code here. This method is called before the invocation of each test method in the + // class. + [super setUp]; + self.modelPath = [[NSBundle bundleForClass:[self class]] + pathForResource:@"coco_ssd_mobilenet_v1_1.0_quant_2018_06_29" + ofType:@"tflite"]; + XCTAssertNotNil(self.modelPath); +} + +- (void)verifyResults:(TFLDetectionResult *)detectionResult { + XCTAssertGreaterThan([detectionResult.detections count], 0); + VerifyDetection(detectionResult.detections[0], + CGRectMake(54, 396, 393, 199), // expectedBoundingBox + 0.632812, // expectedFirstScore + @"cat" // expectedFirstLabel + ); + VerifyDetection(detectionResult.detections[1], + CGRectMake(602, 157, 394, 447), // expectedBoundingBox + 0.609375, // expectedFirstScore + @"cat" // expectedFirstLabel + ); + VerifyDetection(detectionResult.detections[2], + CGRectMake(260, 394, 179, 209), // expectedBoundingBox + 0.5625, // expectedFirstScore + @"cat" // expectedFirstLabel + ); + VerifyDetection(detectionResult.detections[3], + CGRectMake(387, 197, 281, 409), // expectedBoundingBox + 0.488281, // expectedFirstScore + @"dog" // expectedFirstLabel + ); +} + +- (void)testSuccessfullObjectDetectionOnMLImageWithUIImage { + TFLObjectDetectorOptions *objectDetectorOptions = + [[TFLObjectDetectorOptions alloc] initWithModelPath:self.modelPath]; + + TFLObjectDetector *objectDetector = + [TFLObjectDetector objectDetectorWithOptions:objectDetectorOptions error:nil]; + XCTAssertNotNil(objectDetector); + + GMLImage *gmlImage = [GMLImage imageFromBundleWithClass:[self class] + fileName:@"cats_and_dogs" + ofType:@"jpg"]; + XCTAssertNotNil(gmlImage); + + TFLDetectionResult *detectionResults = [objectDetector detectWithGMLImage:gmlImage error:nil]; + [self verifyResults:detectionResults]; +} + +- (void)testModelOptionsWithMaxResults { + TFLObjectDetectorOptions *objectDetectorOptions = + [[TFLObjectDetectorOptions alloc] initWithModelPath:self.modelPath]; + int maxResults = 3; + objectDetectorOptions.classificationOptions.maxResults = maxResults; + + TFLObjectDetector *objectDetector = + [TFLObjectDetector objectDetectorWithOptions:objectDetectorOptions error:nil]; + XCTAssertNotNil(objectDetector); + + GMLImage *gmlImage = [GMLImage imageFromBundleWithClass:[self class] + fileName:@"cats_and_dogs" + ofType:@"jpg"]; + XCTAssertNotNil(gmlImage); + + TFLDetectionResult *detectionResult = [objectDetector detectWithGMLImage:gmlImage error:nil]; + + XCTAssertLessThanOrEqual([detectionResult.detections count], maxResults); + VerifyDetection(detectionResult.detections[0], + CGRectMake(54, 396, 393, 199), // expectedBoundingBox + 0.632812, // expectedFirstScore + @"cat" // expectedFirstLabel + ); + VerifyDetection(detectionResult.detections[1], + CGRectMake(602, 157, 394, 447), // expectedBoundingBox + 0.609375, // expectedFirstScore + @"cat" // expectedFirstLabel + ); + VerifyDetection(detectionResult.detections[2], + CGRectMake(260, 394, 179, 209), // expectedBoundingBox + 0.5625, // expectedFirstScore + @"cat" // expectedFirstLabel + ); +} + +@end
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/object_detector/TFLObjectDetectorTests.swift b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/object_detector/TFLObjectDetectorTests.swift new file mode 100644 index 0000000..b52eda1 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/object_detector/TFLObjectDetectorTests.swift
@@ -0,0 +1,143 @@ +/* Copyright 2022 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +import GMLImageHelpers +import XCTest + +@testable import TFLObjectDetector + +class TFLObjectDetectorTests: XCTestCase { + + static let bundle = Bundle(for: TFLObjectDetectorTests.self) + static let modelPath = bundle.path( + forResource: "coco_ssd_mobilenet_v1_1.0_quant_2018_06_29", + ofType: "tflite")! + + func verifyDetectionResult(_ detectionResult: TFLDetectionResult) { + XCTAssertGreaterThan(detectionResult.detections.count, 0) + + self.verifyDetection( + detectionResult.detections[0], + expectedBoundingBox: CGRect(x: 54, y: 396, width: 393, height: 199), + expectedFirstScore: 0.632812, + expectedFirstLabel: "cat") + + self.verifyDetection( + detectionResult.detections[1], + expectedBoundingBox: CGRect(x: 602, y: 157, width: 394, height: 447), + expectedFirstScore: 0.609375, + expectedFirstLabel: "cat") + + self.verifyDetection( + detectionResult.detections[2], + expectedBoundingBox: CGRect(x: 260, y: 394, width: 179, height: 209), + expectedFirstScore: 0.5625, + expectedFirstLabel: "cat") + + self.verifyDetection( + detectionResult.detections[3], + expectedBoundingBox: CGRect(x: 387, y: 197, width: 281, height: 409), + expectedFirstScore: 0.488281, + expectedFirstLabel: "dog") + } + + func verifyDetection( + _ detection: TFLDetection, expectedBoundingBox: CGRect, + expectedFirstScore: Float, + expectedFirstLabel: String + ) { + XCTAssertGreaterThan(detection.categories.count, 0) + XCTAssertEqual( + detection.boundingBox.origin.x, + expectedBoundingBox.origin.x) + XCTAssertEqual( + detection.boundingBox.origin.y, + expectedBoundingBox.origin.y) + XCTAssertEqual( + detection.boundingBox.size.width, + expectedBoundingBox.size.width) + XCTAssertEqual( + detection.boundingBox.size.height, + expectedBoundingBox.size.height) + XCTAssertEqual( + detection.categories[0].label, + expectedFirstLabel) + XCTAssertEqualWithAccuracy( + detection.categories[0].score, + expectedFirstScore, accuracy: 0.001) + } + + func testSuccessfullInferenceOnMLImageWithUIImage() throws { + + let modelPath = try XCTUnwrap(TFLObjectDetectorTests.modelPath) + + let objectDetectorOptions = TFLObjectDetectorOptions(modelPath: modelPath) + XCTAssertNotNil(objectDetectorOptions) + + let objectDetector = + try TFLObjectDetector.objectDetector(options: objectDetectorOptions!) + + let gmlImage = try XCTUnwrap( + MLImage.imageFromBundle( + class: type(of: self), + filename: "cats_and_dogs", + type: "jpg")) + let detectionResults: TFLDetectionResult = + try objectDetector.detect(gmlImage: gmlImage) + + self.verifyDetectionResult(detectionResults) + } + + func testModelOptionsWithMaxResults() throws { + + let modelPath = try XCTUnwrap(TFLObjectDetectorTests.modelPath) + + let objectDetectorOptions = TFLObjectDetectorOptions(modelPath: modelPath) + XCTAssertNotNil(objectDetectorOptions) + + let maxResults = 3 + objectDetectorOptions!.classificationOptions.maxResults = maxResults + + let objectDetector = + try TFLObjectDetector.objectDetector(options: objectDetectorOptions!) + + let gmlImage = try XCTUnwrap( + MLImage.imageFromBundle( + class: type(of: self), + filename: "cats_and_dogs", + type: "jpg")) + let detectionResult: TFLDetectionResult = try objectDetector.detect( + gmlImage: gmlImage) + + XCTAssertLessThanOrEqual(detectionResult.detections.count, maxResults) + + self.verifyDetection( + detectionResult.detections[0], + expectedBoundingBox: CGRect(x: 54, y: 396, width: 393, height: 199), + expectedFirstScore: 0.632812, + expectedFirstLabel: "cat") + + self.verifyDetection( + detectionResult.detections[1], + expectedBoundingBox: CGRect(x: 602, y: 157, width: 394, height: 447), + expectedFirstScore: 0.609375, + expectedFirstLabel: "cat") + + self.verifyDetection( + detectionResult.detections[2], + expectedBoundingBox: CGRect(x: 260, y: 394, width: 179, height: 209), + expectedFirstScore: 0.5625, + expectedFirstLabel: "cat") + } +}
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/BUILD new file mode 100644 index 0000000..1b54637 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/BUILD
@@ -0,0 +1,18 @@ +package( + default_visibility = ["//tensorflow_lite_support:__subpackages__"], + licenses = ["notice"], # Apache 2.0 +) + +objc_library( + name = "GMLImageHelpers", + srcs = [ + "sources/GMLImage+Helpers.m", + ], + hdrs = [ + "sources/GMLImage+Helpers.h", + ], + module_name = "GMLImageHelpers", + deps = [ + "//tensorflow_lite_support/odml/ios/image:MLImage", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.h new file mode 100644 index 0000000..8192fa1 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.h
@@ -0,0 +1,28 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#import "tensorflow_lite_support/odml/ios/image/apis/GMLImage.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface GMLImage (Helpers) + ++ (nullable GMLImage*)imageFromBundleWithClass:(Class)classObject + fileName:(NSString*)name + ofType:(NSString*)type + NS_SWIFT_NAME(imageFromBundle(class:filename:type:)); + +@end + +NS_ASSUME_NONNULL_END
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.m b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.m new file mode 100644 index 0000000..f1e91af --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.m
@@ -0,0 +1,31 @@ +/* Copyright 2021 The TensorFlow Authors. All Rights Reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ==============================================================================*/ +#import "tensorflow_lite_support/ios/test/task/vision/utils/sources/GMLImage+Helpers.h" + +@implementation GMLImage (Helpers) + ++ (GMLImage *)imageFromBundleWithClass:(Class)classObject + fileName:(NSString *)name + ofType:(NSString *)type { + NSString *imagePath = [[NSBundle bundleForClass:classObject] pathForResource:name ofType:type]; + if (!imagePath) return nil; + + UIImage *image = [[UIImage alloc] initWithContentsOfFile:imagePath]; + if (!image) return nil; + + return [[GMLImage alloc] initWithImage:image]; +} + +@end
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.h index d08f5177..c10c82a 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.h
@@ -12,7 +12,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#import "third_party/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizer.h" +#import "tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizer.h" NS_ASSUME_NONNULL_BEGIN /**
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.mm b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.mm index 2a028f6..949cef2 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.mm +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLBertTokenizer.mm
@@ -24,7 +24,7 @@ std::unique_ptr<BertTokenizerCPP> _bertTokenizer; } -- (instancetype)initWithVocabPath:(NSString*)vocabPath { +- (instancetype)initWithVocabPath:(NSString *)vocabPath { self = [super init]; if (self) { _bertTokenizer = absl::make_unique<BertTokenizerCPP>(MakeString(vocabPath)); @@ -32,12 +32,12 @@ return self; } -- (instancetype)initWithVocab:(NSArray<NSString*>*)vocab { +- (instancetype)initWithVocab:(NSArray<NSString *> *)vocab { self = [super init]; if (self) { std::vector<std::string> vocabCpp; vocabCpp.reserve([vocab count]); - for (NSString* word in vocab) { + for (NSString *word in vocab) { vocabCpp.emplace_back(MakeString(word)); } _bertTokenizer = absl::make_unique<BertTokenizerCPP>(vocabCpp); @@ -45,11 +45,11 @@ return self; } -- (NSArray<NSString*>*)tokensFromInput:(NSString*)input { +- (NSArray<NSString *> *)tokensFromInput:(NSString *)input { return Tokenize(_bertTokenizer.get(), input); } -- (NSArray<NSNumber*>*)idsFromTokens:(NSArray<NSString*>*)tokens { +- (NSArray<NSNumber *> *)idsFromTokens:(NSArray<NSString *> *)tokens { return ConvertTokensToIds(_bertTokenizer.get(), tokens); }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.h b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.h index 9813e32..be4010a 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.h
@@ -12,7 +12,7 @@ See the License for the specific language governing permissions and limitations under the License. ==============================================================================*/ -#import "third_party/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizer.h" +#import "tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizer.h" NS_ASSUME_NONNULL_BEGIN /**
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.mm b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.mm index 1ba4992..1e21cee5 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.mm +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLSentencepieceTokenizer.mm
@@ -19,27 +19,25 @@ #import "third_party/tensorflow_lite_support/ios/utils/Sources/TFLStringUtil.h" NS_ASSUME_NONNULL_BEGIN -using SentencepieceTokenizerCPP = - ::tflite::support::text::tokenizer::SentencePieceTokenizer; +using SentencepieceTokenizerCPP = ::tflite::support::text::tokenizer::SentencePieceTokenizer; @implementation TFLSentencepieceTokenizer { std::unique_ptr<SentencepieceTokenizerCPP> _spTokenizer; } -- (instancetype)initWithModelPath:(NSString*)modelPath { +- (instancetype)initWithModelPath:(NSString *)modelPath { self = [super init]; if (self) { - _spTokenizer = - absl::make_unique<SentencepieceTokenizerCPP>(MakeString(modelPath)); + _spTokenizer = absl::make_unique<SentencepieceTokenizerCPP>(MakeString(modelPath)); } return self; } -- (NSArray<NSString*>*)tokensFromInput:(NSString*)input { +- (NSArray<NSString *> *)tokensFromInput:(NSString *)input { return Tokenize(_spTokenizer.get(), input); } -- (NSArray<NSNumber*>*)idsFromTokens:(NSArray<NSString*>*)tokens { +- (NSArray<NSNumber *> *)idsFromTokens:(NSArray<NSString *> *)tokens { return ConvertTokensToIds(_spTokenizer.get(), tokens); }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizerUtil.mm b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizerUtil.mm index 8e92e37..5218057 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizerUtil.mm +++ b/third_party/tflite_support/src/tensorflow_lite_support/ios/text/tokenizers/Sources/TFLTokenizerUtil.mm
@@ -18,24 +18,21 @@ using ::tflite::support::text::tokenizer::TokenizerResult; -NSArray<NSString*>* Tokenize(Tokenizer* tokenizer, NSString* input) { +NSArray<NSString *> *Tokenize(Tokenizer *tokenizer, NSString *input) { TokenizerResult tokenize_result = tokenizer->Tokenize(MakeString(input)); std::vector<std::string> subwords = tokenize_result.subwords; - NSMutableArray<NSString*>* ret = - [NSMutableArray arrayWithCapacity:subwords.size()]; + NSMutableArray<NSString *> *ret = [NSMutableArray arrayWithCapacity:subwords.size()]; for (int i = 0; i < subwords.size(); ++i) { [ret addObject:MakeNSString(subwords[i])]; } return ret; } -NSArray<NSNumber*>* ConvertTokensToIds(Tokenizer* tokenizer, - NSArray<NSString*>* tokens) { - NSMutableArray<NSNumber*>* ret = - [NSMutableArray arrayWithCapacity:[tokens count]]; - for (NSString* token in tokens) { +NSArray<NSNumber *> *ConvertTokensToIds(Tokenizer *tokenizer, NSArray<NSString *> *tokens) { + NSMutableArray<NSNumber *> *ret = [NSMutableArray arrayWithCapacity:[tokens count]]; + for (NSString *token in tokens) { std::string cc_token = MakeString(token); - const char* cToken = cc_token.c_str(); + const char *cToken = cc_token.c_str(); int id; tokenizer->LookupId(cToken, &id); [ret addObject:[NSNumber numberWithInt:id]];
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/java/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/java/BUILD index 4076307c..3dad1e1 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/java/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/java/BUILD
@@ -19,15 +19,14 @@ srcs = glob(["src/java/org/tensorflow/lite/support/**/*.java"]), ) -# Android Library target for TFLite Support Library. It depends on TensorFlow -# Lite runtime (tensorflow/lite/java:tensorflowlite). If you don't want to -# introduce the native library into dependencies, use -# "tensorflowlite_support_java" instead, which depends on -# tensorflow/lite/java:tensorflowlite_java_stable. +# Android Library target for TFLite Support Library. It depends on the +# TensorFlow Lite Runtime (tensorflow/lite/java:tensorflowlite), +# including its associated native code. If you don't want to introduce the native +# library into dependencies, use "tensorflowlite_support_java" instead, +# which depends on tensorflow/lite/java:tensorflowlite_api. android_library( name = "tensorflowlite_support", srcs = [], - javacopts = ["-source 7 -target 7"], manifest = "AndroidManifest.xml", exports = [ ":tensorflowlite_support_java", @@ -38,10 +37,14 @@ ], ) +# Android Library target for TFLite Support Library, excluding native code, +# and excluding dependencies on the TensorFlow Lite Runtime. +# If you use this target, a TensorFlow Lite Runtime (and it's associated +# native code) is nevertheless still required, and must be provided by a +# separate dependency. android_library( name = "tensorflowlite_support_java", srcs = [":java_srcs"], - javacopts = ["-source 7 -target 7"], manifest = "AndroidManifest.xml", # LINT.IfChange(dep) deps = [ @@ -49,7 +52,7 @@ "@maven//:androidx_annotation_annotation", "@maven//:com_google_android_odml_image", "@org_checkerframework_qual", - "@org_tensorflow//tensorflow/lite/java:tensorflowlite_java_stable", # TODO(b/198734357): Use api when TF dep catches up. + "@org_tensorflow//tensorflow/lite/java:tensorflowlite_api", ], # LINT.ThenChange(<INTERNAL>/release/build_support_api_pom.sh:dep) )
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/java/src/java/org/tensorflow/lite/support/model/Model.java b/third_party/tflite_support/src/tensorflow_lite_support/java/src/java/org/tensorflow/lite/support/model/Model.java index af2061e..282f2b9 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/java/src/java/org/tensorflow/lite/support/model/Model.java +++ b/third_party/tflite_support/src/tensorflow_lite_support/java/src/java/org/tensorflow/lite/support/model/Model.java
@@ -20,7 +20,7 @@ import org.checkerframework.checker.nullness.qual.NonNull; import org.checkerframework.checker.nullness.qual.Nullable; import org.tensorflow.lite.InterpreterApi; -import org.tensorflow.lite.InterpreterFactory; +import org.tensorflow.lite.InterpreterApi.Options.TfLiteRuntime; import org.tensorflow.lite.Tensor; import org.tensorflow.lite.support.common.FileUtil; import org.tensorflow.lite.support.common.internal.SupportPreconditions; @@ -52,11 +52,13 @@ public static class Options { private final Device device; private final int numThreads; + private final TfLiteRuntime tfLiteRuntime; /** Builder of {@link Options}. See its doc for details. */ public static class Builder { private Device device = Device.CPU; private int numThreads = 1; + private TfLiteRuntime tfLiteRuntime; public Builder setDevice(Device device) { this.device = device; @@ -68,6 +70,11 @@ return this; } + public Builder setTfLiteRuntime(TfLiteRuntime tfLiteRuntime) { + this.tfLiteRuntime = tfLiteRuntime; + return this; + } + public Options build() { return new Options(this); } @@ -76,6 +83,7 @@ private Options(Builder builder) { device = builder.device; numThreads = builder.numThreads; + tfLiteRuntime = builder.tfLiteRuntime; } } @@ -109,7 +117,6 @@ * @param modelPath Asset path of the model (.tflite file). * @throws IOException if an I/O error occurs when loading the tflite model. */ - @NonNull public Builder(@NonNull Context context, @NonNull String modelPath) throws IOException { this.modelPath = modelPath; byteModel = FileUtil.loadMappedFile(context, modelPath); @@ -199,7 +206,10 @@ break; } interpreterOptions.setNumThreads(options.numThreads); - InterpreterApi interpreter = new InterpreterFactory().create(byteModel, interpreterOptions); + if (options.tfLiteRuntime != null) { + interpreterOptions.setRuntime(options.tfLiteRuntime); + } + InterpreterApi interpreter = InterpreterApi.create(byteModel, interpreterOptions); return new Model(modelPath, byteModel, interpreter, gpuDelegateProxy); }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/metadata/cc/metadata_version.cc b/third_party/tflite_support/src/tensorflow_lite_support/metadata/cc/metadata_version.cc index ed75b656e..2e2f2fa 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/metadata/cc/metadata_version.cc +++ b/third_party/tflite_support/src/tensorflow_lite_support/metadata/cc/metadata_version.cc
@@ -22,8 +22,8 @@ #include <string> #include <vector> -#include "absl/strings/str_join.h" // from @com_google_absl -#include "absl/strings/str_split.h" // from @com_google_absl +#include "absl/strings/str_join.h" // from @com_google_absl +#include "absl/strings/str_split.h" // from @com_google_absl #include "flatbuffers/flatbuffers.h" // from @flatbuffers #include "tensorflow/lite/c/common.h" #include "tensorflow/lite/kernels/internal/compatibility.h"
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/BUILD index 3668e49..91f7ad68 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/BUILD +++ b/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/BUILD
@@ -47,6 +47,9 @@ name = "metadata_writer_for_task", srcs = ["metadata_writer_for_task.py"], srcs_version = "PY3", + visibility = [ + "//tensorflow_lite_support:users", + ], deps = [ ":metadata", "//tensorflow_lite_support/metadata:metadata_schema_py",
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/metadata_writer_for_task.py b/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/metadata_writer_for_task.py index 8d2a9b8..1ea8c40 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/metadata_writer_for_task.py +++ b/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/metadata_writer_for_task.py
@@ -190,6 +190,14 @@ _INPUT_AUDIO_NAME = 'audio' _INPUT_AUDIO_DESCRIPTION = 'Input audio clip to be processed.' + def add_feature_input(self, + name: Optional[str] = None, + description: Optional[str] = None) -> 'Writer': + """Marks the next input tensor as a basic feature input.""" + input_md = metadata_info.TensorMd(name=name, description=description) + self._input_mds.append(input_md) + return self + def add_audio_input(self, sample_rate: int, channels: int, @@ -224,7 +232,7 @@ color_space_type: Optional[ _metadata_fb.ColorSpaceType] = _metadata_fb.ColorSpaceType.RGB, name: str = _INPUT_IMAGE_NAME, - description: str = _INPUT_IMAGE_DESCRIPTION): + description: str = _INPUT_IMAGE_DESCRIPTION) -> 'Writer': """Marks the next input tensor as an image input. Args: @@ -261,6 +269,14 @@ _OUTPUT_EMBEDDING_NAME = 'embedding' _OUTPUT_EMBEDDING_DESCRIPTION = 'Embedding vector of the input.' + def add_feature_output(self, + name: Optional[str] = None, + description: Optional[str] = None) -> 'Writer': + """Marks the next input tensor as a basic feature output.""" + output_md = metadata_info.TensorMd(name=name, description=description) + self._output_mds.append(output_md) + return self + def add_embedding_output(self, name: str = _OUTPUT_EMBEDDING_NAME, description: str = _OUTPUT_EMBEDDING_DESCRIPTION): @@ -297,7 +313,7 @@ labels: Labels, score_calibration: Optional[ScoreCalibration] = None, name=_OUTPUT_CLASSIFICATION_NAME, - description=_OUTPUT_CLASSIFICATION_DESCRIPTION): + description=_OUTPUT_CLASSIFICATION_DESCRIPTION) -> 'Writer': """Marks model's next output tensor as a classification head. Example usage:
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/tests/metadata_writer_for_task_test.py b/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/tests/metadata_writer_for_task_test.py index 8c4f331..32d17a2 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/tests/metadata_writer_for_task_test.py +++ b/third_party/tflite_support/src/tensorflow_lite_support/metadata/python/tests/metadata_writer_for_task_test.py
@@ -113,6 +113,59 @@ } """) + def test_general_model(self): + with mt.Writer( + test_utils.load_file(_AUDIO_CLASSIFICATION_MODEL), + model_name='my_model', + model_description='my_description') as writer: + writer.add_feature_input( + name='input_tesnor', description='a feature input tensor') + writer.add_feature_output( + name='output_tesnor', description='a feature output tensor') + + out_dir = self.create_tempdir() + writer.populate( + os.path.join(out_dir, 'model.tflite'), + os.path.join(out_dir, 'metadata.tflite')) + self.assertEqual( + test_utils.load_file(os.path.join(out_dir, 'metadata.tflite'), 'r'), + """{ + "name": "my_model", + "description": "my_description", + "subgraph_metadata": [ + { + "input_tensor_metadata": [ + { + "name": "input_tesnor", + "description": "a feature input tensor", + "content": { + "content_properties_type": "FeatureProperties", + "content_properties": { + } + }, + "stats": { + } + } + ], + "output_tensor_metadata": [ + { + "name": "output_tesnor", + "description": "a feature output tensor", + "content": { + "content_properties_type": "FeatureProperties", + "content_properties": { + } + }, + "stats": { + } + } + ] + } + ], + "min_parser_version": "1.0.0" +} +""") + def test_audio_classifier(self): with mt.Writer( test_utils.load_file(_AUDIO_CLASSIFICATION_MODEL),
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/apis/GMLImage.h b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/apis/GMLImage.h index 0c49491..18797d8 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/apis/GMLImage.h +++ b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/apis/GMLImage.h
@@ -19,8 +19,8 @@ NS_ASSUME_NONNULL_BEGIN /** Types of image sources. */ -typedef NSInteger GMLImageSourceType NS_TYPED_ENUM - NS_SWIFT_NAME(MLImageSourceType); +typedef NSInteger GMLImageSourceType + NS_TYPED_ENUM NS_SWIFT_NAME(MLImageSourceType); /** Image source is a `UIImage`. */ static const GMLImageSourceType GMLImageSourceTypeImage = 0; /** Image source is a `CVPixelBuffer`. */
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/sources/GMLImage.m b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/sources/GMLImage.m index 38ca7426..094d4e0 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/sources/GMLImage.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/sources/GMLImage.m
@@ -20,7 +20,7 @@ #pragma mark - Public -- (nullable instancetype)initWithImage:(UIImage*)image { +- (nullable instancetype)initWithImage:(UIImage *)image { if (image.CGImage == NULL) { return nil; }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/tests/GMLImageTests.m b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/tests/GMLImageTests.m index 8abee1a..5920574 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/tests/GMLImageTests.m +++ b/third_party/tflite_support/src/tensorflow_lite_support/odml/ios/image/tests/GMLImageTests.m
@@ -22,8 +22,8 @@ NS_ASSUME_NONNULL_BEGIN -static NSString* const kTestImageName = @"grace_hopper"; -static NSString* const kTestImageType = @"jpg"; +static NSString *const kTestImageName = @"grace_hopper"; +static NSString *const kTestImageType = @"jpg"; static CGFloat kTestImageWidthInPixels = 517.0f; static CGFloat kTestImageHeightInPixels = 606.0f; @@ -31,7 +31,7 @@ @interface GMLImageTests : XCTestCase /** Test image. */ -@property(nonatomic, nullable) UIImage* image; +@property(nonatomic, nullable) UIImage *image; @end @@ -41,9 +41,8 @@ - (void)setUp { [super setUp]; - NSString* imageName = - [[NSBundle bundleForClass:[self class]] pathForResource:kTestImageName - ofType:kTestImageType]; + NSString *imageName = [[NSBundle bundleForClass:[self class]] pathForResource:kTestImageName + ofType:kTestImageType]; self.image = [[UIImage alloc] initWithContentsOfFile:imageName]; } @@ -53,59 +52,53 @@ } - (void)testInitWithImage { - GMLImage* mlImage = [[GMLImage alloc] initWithImage:self.image]; + GMLImage *mlImage = [[GMLImage alloc] initWithImage:self.image]; XCTAssertNotNil(mlImage); XCTAssertEqual(mlImage.imageSourceType, GMLImageSourceTypeImage); XCTAssertEqual(mlImage.orientation, self.image.imageOrientation); mlImage.orientation = UIImageOrientationDown; XCTAssertEqual(mlImage.orientation, UIImageOrientationDown); - XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, - FLT_EPSILON); - XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, - FLT_EPSILON); + XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, FLT_EPSILON); + XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, FLT_EPSILON); } - (void)testInitWithImage_nilImage { - GMLImage* mlImage = [[GMLImage alloc] initWithImage:nil]; + GMLImage *mlImage = [[GMLImage alloc] initWithImage:nil]; XCTAssertNil(mlImage); } - (void)testInitWithSampleBuffer { CMSampleBufferRef sampleBuffer = [self sampleBuffer]; - GMLImage* mlImage = [[GMLImage alloc] initWithSampleBuffer:sampleBuffer]; + GMLImage *mlImage = [[GMLImage alloc] initWithSampleBuffer:sampleBuffer]; XCTAssertNotNil(mlImage); XCTAssertEqual(mlImage.imageSourceType, GMLImageSourceTypeSampleBuffer); XCTAssertEqual(mlImage.orientation, UIImageOrientationUp); mlImage.orientation = UIImageOrientationDown; XCTAssertEqual(mlImage.orientation, UIImageOrientationDown); - XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, - FLT_EPSILON); - XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, - FLT_EPSILON); + XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, FLT_EPSILON); + XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, FLT_EPSILON); } - (void)testInitWithSampleBuffer_nilImage { - GMLImage* mlImage = [[GMLImage alloc] initWithSampleBuffer:nil]; + GMLImage *mlImage = [[GMLImage alloc] initWithSampleBuffer:nil]; XCTAssertNil(mlImage); } - (void)testInitWithPixelBuffer { CMSampleBufferRef sampleBuffer = [self sampleBuffer]; CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer); - GMLImage* mlImage = [[GMLImage alloc] initWithPixelBuffer:pixelBuffer]; + GMLImage *mlImage = [[GMLImage alloc] initWithPixelBuffer:pixelBuffer]; XCTAssertNotNil(mlImage); XCTAssertEqual(mlImage.imageSourceType, GMLImageSourceTypePixelBuffer); XCTAssertEqual(mlImage.orientation, UIImageOrientationUp); mlImage.orientation = UIImageOrientationDown; XCTAssertEqual(mlImage.orientation, UIImageOrientationDown); - XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, - FLT_EPSILON); - XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, - FLT_EPSILON); + XCTAssertEqualWithAccuracy(mlImage.width, kTestImageWidthInPixels, FLT_EPSILON); + XCTAssertEqualWithAccuracy(mlImage.height, kTestImageHeightInPixels, FLT_EPSILON); } - (void)testInitWithPixelBuffer_nilImage { - GMLImage* mlImage = [[GMLImage alloc] initWithPixelBuffer:nil]; + GMLImage *mlImage = [[GMLImage alloc] initWithPixelBuffer:nil]; XCTAssertNil(mlImage); } @@ -124,18 +117,17 @@ size_t bpr = CGImageGetBytesPerRow(CGImage); CGDataProviderRef provider = CGImageGetDataProvider(CGImage); - NSData* imageRGBAData = - (id)CFBridgingRelease(CGDataProviderCopyData(provider)); + NSData *imageRGBAData = (id)CFBridgingRelease(CGDataProviderCopyData(provider)); const uint8_t order[4] = {2, 1, 0, 3}; - NSData* imageBGRAData = nil; - unsigned char* bgraPixel = (unsigned char*)malloc([imageRGBAData length]); + NSData *imageBGRAData = nil; + unsigned char *bgraPixel = (unsigned char *)malloc([imageRGBAData length]); if (bgraPixel) { vImage_Buffer src; src.height = height; src.width = width; src.rowBytes = bpr; - src.data = (void*)[imageRGBAData bytes]; + src.data = (void *)[imageRGBAData bytes]; vImage_Buffer dest; dest.height = height; @@ -144,13 +136,11 @@ dest.data = bgraPixel; // Specify ordering changes in map. - vImage_Error error = - vImagePermuteChannels_ARGB8888(&src, &dest, order, kvImageNoFlags); + vImage_Error error = vImagePermuteChannels_ARGB8888(&src, &dest, order, kvImageNoFlags); // Package the result. if (error == kvImageNoError) { - imageBGRAData = [NSData dataWithBytes:bgraPixel - length:[imageRGBAData length]]; + imageBGRAData = [NSData dataWithBytes:bgraPixel length:[imageRGBAData length]]; } // Memory cleanup. @@ -162,15 +152,14 @@ } // Write data to `CMSampleBuffer`. - NSDictionary* options = @{ - (__bridge NSString*)kCVPixelBufferCGImageCompatibilityKey : @(YES), - (__bridge NSString*)kCVPixelBufferCGBitmapContextCompatibilityKey : @(YES) + NSDictionary *options = @{ + (__bridge NSString *)kCVPixelBufferCGImageCompatibilityKey : @(YES), + (__bridge NSString *)kCVPixelBufferCGBitmapContextCompatibilityKey : @(YES) }; CVPixelBufferRef pixelBuffer; CVReturn status = CVPixelBufferCreateWithBytes( - kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA, - (void*)[imageBGRAData bytes], bpr, NULL, nil, - (__bridge CFDictionaryRef)options, &pixelBuffer); + kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA, (void *)[imageBGRAData bytes], + bpr, NULL, nil, (__bridge CFDictionaryRef)options, &pixelBuffer); if (status != kCVReturnSuccess) { XCTFail(@"Failed to create pixel buffer."); @@ -178,12 +167,10 @@ CVPixelBufferLockBaseAddress(pixelBuffer, 0); CMVideoFormatDescriptionRef videoInfo = NULL; - CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, - &videoInfo); + CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, &videoInfo); CMSampleBufferRef buffer; - CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, true, - NULL, NULL, videoInfo, + CMSampleBufferCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer, true, NULL, NULL, videoInfo, &kCMTimingInfoInvalid, &buffer); CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/opensource/opensource_only.files b/third_party/tflite_support/src/tensorflow_lite_support/opensource/opensource_only.files index 71f2c89..728b1ecb 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/opensource/opensource_only.files +++ b/third_party/tflite_support/src/tensorflow_lite_support/opensource/opensource_only.files
@@ -1,45 +1,45 @@ -tensorflow_lite_support/cc/port/build_defs.bzl -tensorflow_lite_support/custom_ops/kernel/sentencepiece/native.bzl -tensorflow_lite_support/opensource/.bazelversion -tensorflow_lite_support/opensource/BUILD -tensorflow_lite_support/opensource/WORKSPACE -tensorflow_lite_support/third_party/android/BUILD -tensorflow_lite_support/third_party/android/android.bzl.tpl -tensorflow_lite_support/third_party/android/android_configure.BUILD.tpl -tensorflow_lite_support/third_party/android/android_configure.bzl -tensorflow_lite_support/third_party/com_google_absl.BUILD -tensorflow_lite_support/third_party/darts_clone.BUILD -tensorflow_lite_support/third_party/fft2d/BUILD -tensorflow_lite_support/third_party/fft2d/LICENSE -tensorflow_lite_support/third_party/fft2d/fft.h -tensorflow_lite_support/third_party/fft2d/fft2d.BUILD -tensorflow_lite_support/third_party/fft2d/fft2d.h -tensorflow_lite_support/third_party/google_toolbox_for_mac.BUILD -tensorflow_lite_support/third_party/icu.BUILD -tensorflow_lite_support/third_party/libyuv.BUILD -tensorflow_lite_support/third_party/libzip.BUILD -tensorflow_lite_support/third_party/pybind11.BUILD -tensorflow_lite_support/third_party/python_runtime/BUILD -tensorflow_lite_support/third_party/six.BUILD -tensorflow_lite_support/third_party/stblib.BUILD -tensorflow_lite_support/third_party/toolchains/java/BUILD -tensorflow_lite_support/third_party/utf.BUILD -tensorflow_lite_support/third_party/zlib.BUILD -tensorflow_lite_support/tools/build_rules/android_test/AndroidManifest_instrumentation_test_template.xml -tensorflow_lite_support/tools/build_rules/android_test/AndroidManifest_target_stub.xml -tensorflow_lite_support/tools/build_rules/android_test/android_library_instrumentation_tests.bzl -tensorflow_lite_support/tools/build_rules/android_test/android_multidevice_instrumentation_test.bzl -tensorflow_lite_support/tools/build_rules/android_test/generate_instrumentation_tests.bzl -tensorflow_lite_support/tools/build_rules/android_test/infer_java_package_name.bzl -tensorflow_lite_support/tools/build_rules/http_files.bzl -tensorflow_lite_support/tools/ci_build/build_all.sh -tensorflow_lite_support/tools/ci_build/common.sh -tensorflow_lite_support/tools/ci_build/common_win.bat -tensorflow_lite_support/tools/pip_package/BUILD -tensorflow_lite_support/tools/pip_package/MANIFEST.in -tensorflow_lite_support/tools/pip_package/README -tensorflow_lite_support/tools/pip_package/build_pip_package.sh -tensorflow_lite_support/tools/pip_package/metadata_writers.__init__.py -tensorflow_lite_support/tools/pip_package/setup.py -tensorflow_lite_support/tools/pip_package/simple_console_for_windows.py -tensorflow_lite_support/tools/pip_package/tflite_support.__init__.py \ No newline at end of file +tensorflow_lite_support/cc/port/build_defs.bzl: +tensorflow_lite_support/custom_ops/kernel/sentencepiece/native.bzl: +tensorflow_lite_support/opensource/.bazelversion: +tensorflow_lite_support/opensource/BUILD: +tensorflow_lite_support/opensource/WORKSPACE: +tensorflow_lite_support/third_party/android/BUILD: +tensorflow_lite_support/third_party/android/android.bzl.tpl: +tensorflow_lite_support/third_party/android/android_configure.BUILD.tpl: +tensorflow_lite_support/third_party/android/android_configure.bzl: +tensorflow_lite_support/third_party/com_google_absl.BUILD: +tensorflow_lite_support/third_party/darts_clone.BUILD: +tensorflow_lite_support/third_party/fft2d/BUILD: +tensorflow_lite_support/third_party/fft2d/LICENSE: +tensorflow_lite_support/third_party/fft2d/fft.h: +tensorflow_lite_support/third_party/fft2d/fft2d.BUILD: +tensorflow_lite_support/third_party/fft2d/fft2d.h: +tensorflow_lite_support/third_party/google_toolbox_for_mac.BUILD: +tensorflow_lite_support/third_party/icu.BUILD: +tensorflow_lite_support/third_party/libyuv.BUILD: +tensorflow_lite_support/third_party/libzip.BUILD: +tensorflow_lite_support/third_party/pybind11.BUILD: +tensorflow_lite_support/third_party/python_runtime/BUILD: +tensorflow_lite_support/third_party/six.BUILD: +tensorflow_lite_support/third_party/stblib.BUILD: +tensorflow_lite_support/third_party/toolchains/java/BUILD: +tensorflow_lite_support/third_party/utf.BUILD: +tensorflow_lite_support/third_party/zlib.BUILD: +tensorflow_lite_support/tools/build_rules/android_test/AndroidManifest_instrumentation_test_template.xml: +tensorflow_lite_support/tools/build_rules/android_test/AndroidManifest_target_stub.xml: +tensorflow_lite_support/tools/build_rules/android_test/android_library_instrumentation_tests.bzl: +tensorflow_lite_support/tools/build_rules/android_test/android_multidevice_instrumentation_test.bzl: +tensorflow_lite_support/tools/build_rules/android_test/generate_instrumentation_tests.bzl: +tensorflow_lite_support/tools/build_rules/android_test/infer_java_package_name.bzl: +tensorflow_lite_support/tools/build_rules/http_files.bzl: +tensorflow_lite_support/tools/ci_build/build_all.sh: +tensorflow_lite_support/tools/ci_build/common.sh: +tensorflow_lite_support/tools/ci_build/common_win.bat: +tensorflow_lite_support/tools/pip_package/BUILD: +tensorflow_lite_support/tools/pip_package/MANIFEST.in: +tensorflow_lite_support/tools/pip_package/README: +tensorflow_lite_support/tools/pip_package/build_pip_package.sh: +tensorflow_lite_support/tools/pip_package/metadata_writers.__init__.py: +tensorflow_lite_support/tools/pip_package/setup.py: +tensorflow_lite_support/tools/pip_package/simple_console_for_windows.py: +tensorflow_lite_support/tools/pip_package/tflite_support.__init__.py:
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/__init__.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/__init__.py new file mode 100644 index 0000000..e04127d --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/__init__.py
@@ -0,0 +1,13 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License.
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/BUILD new file mode 100644 index 0000000..ba30e5c --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/BUILD
@@ -0,0 +1,11 @@ +# Placeholder for internal Python strict library compatibility macro. + +package( + default_visibility = ["//tensorflow_lite_support:internal"], + licenses = ["notice"], # Apache 2.0 +) + +py_library( + name = "task_options", + srcs = ["task_options.py"], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/__init__.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/__init__.py new file mode 100644 index 0000000..e04127d --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/__init__.py
@@ -0,0 +1,13 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License.
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/proto/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/proto/BUILD new file mode 100644 index 0000000..e7b95c66 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/proto/BUILD
@@ -0,0 +1,14 @@ +# Placeholder for internal Python strict library compatibility macro. + +package( + default_visibility = [ + "//tensorflow_lite_support:internal", + ], + licenses = ["notice"], # Apache 2.0 +) + +py_library( + name = "configuration_pb2", + srcs = ["configuration_pb2.py"], + deps = ["@org_tensorflow//tensorflow/lite/experimental/acceleration/configuration:configuration_proto_external_py"], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/proto/__init__.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/proto/__init__.py new file mode 100644 index 0000000..e04127d --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/proto/__init__.py
@@ -0,0 +1,13 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License.
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/proto/configuration_pb2.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/proto/configuration_pb2.py new file mode 100644 index 0000000..f480d6ac --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/proto/configuration_pb2.py
@@ -0,0 +1,18 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Allowlist protobuf.""" + +from tensorflow.lite.experimental.acceleration.configuration import configuration_pb2 + +Delegate = configuration_pb2.Delegate
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/task_options.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/task_options.py new file mode 100644 index 0000000..69be1f3 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/core/task_options.py
@@ -0,0 +1,57 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Options to configure Task APIs.""" + +import dataclasses + +from typing import Optional + + +@dataclasses.dataclass +class ExternalFile: + """Represents external files used by the Task APIs. + + The files can be specified by one of the following + two ways: + + (1) file contents loaded in `file_content`. + (2) file path in `file_name`. + + If more than one field of these fields is provided, they are used in this + precedence order. + """ + # The file contents as a byte array. + file_content: Optional[bytearray] = None + + # The path to the file to open and mmap in memory. + file_name: Optional[str] = None + + +@dataclasses.dataclass +class BaseOptions: + """Base options that is used for creation of any type of task.""" + # The external model file, as a single standalone TFLite file. It could be + # packed with TFLite Model Metadata[1] and associated files if exist. Failure + # to provide the necessary metadata and associated files might result in + # errors. + # Check the documentation for each task about the specific requirement. + # [1]: https://www.tensorflow.org/lite/convert/metadata + model_file: ExternalFile + + # Number of thread: the defaule value -1 means Interpreter will decide what + # is the most appropriate num_threads. + num_threads: int = -1 + + # If true, inference will be delegated to a connected Coral Edge TPU device. + use_coral: bool = False
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/BUILD new file mode 100644 index 0000000..31c5b6c --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/BUILD
@@ -0,0 +1,24 @@ +# Placeholder for internal Python strict library compatibility macro. + +package( + default_visibility = ["//tensorflow_lite_support:internal"], + licenses = ["notice"], # Apache 2.0 +) + +py_library( + name = "embeddings_pb2", + srcs = ["embeddings_pb2.py"], + deps = ["//tensorflow_lite_support/cc/task/vision/proto:embeddings_py_pb2"], +) + +py_library( + name = "embedding_options_pb2", + srcs = ["embedding_options_pb2.py"], + deps = ["//tensorflow_lite_support/cc/task/processor/proto:embedding_options_py_pb2"], +) + +py_library( + name = "bounding_box_pb2", + srcs = ["bounding_box_pb2.py"], + deps = ["//tensorflow_lite_support/cc/task/vision/proto:bounding_box_py_pb2"], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/__init__.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/__init__.py new file mode 100644 index 0000000..e04127d --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/__init__.py
@@ -0,0 +1,13 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License.
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/bounding_box_pb2.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/bounding_box_pb2.py new file mode 100644 index 0000000..fd870a73 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/bounding_box_pb2.py
@@ -0,0 +1,18 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Bounding box protobuf.""" + +from tensorflow_lite_support.cc.task.vision.proto import bounding_box_pb2 + +BoundingBox = bounding_box_pb2.BoundingBox
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/embedding_options_pb2.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/embedding_options_pb2.py new file mode 100644 index 0000000..44f8e6cc --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/embedding_options_pb2.py
@@ -0,0 +1,18 @@ +# Copyright 2022 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Embedding options protobuf.""" + +from tensorflow_lite_support.cc.task.processor.proto import embedding_options_pb2 + +EmbeddingOptions = embedding_options_pb2.EmbeddingOptions
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/embeddings_pb2.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/embeddings_pb2.py new file mode 100644 index 0000000..94e07c2 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/processor/proto/embeddings_pb2.py
@@ -0,0 +1,20 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Embedding result protobuf.""" + +from tensorflow_lite_support.cc.task.vision.proto import embeddings_pb2 + +FeatureVector = embeddings_pb2.FeatureVector +Embedding = embeddings_pb2.Embedding +EmbeddingResult = embeddings_pb2.EmbeddingResult
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/BUILD new file mode 100644 index 0000000..59e2d82 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/BUILD
@@ -0,0 +1,24 @@ +# Placeholder for internal Python strict library compatibility macro. + +package( + default_visibility = ["//tensorflow_lite_support:internal"], + licenses = ["notice"], # Apache 2.0 +) + +py_library( + name = "image_embedder", + srcs = [ + "image_embedder.py", + ], + deps = [ + "//tensorflow_lite_support/python/task/core:task_options", + "//tensorflow_lite_support/python/task/core/proto:configuration_pb2", + "//tensorflow_lite_support/python/task/processor/proto:bounding_box_pb2", + "//tensorflow_lite_support/python/task/processor/proto:embedding_options_pb2", + "//tensorflow_lite_support/python/task/processor/proto:embeddings_pb2", + "//tensorflow_lite_support/python/task/vision/core:tensor_image", + "//tensorflow_lite_support/python/task/vision/core/pybinds:image_utils", + "//tensorflow_lite_support/python/task/vision/pybinds:image_embedder", + "//tensorflow_lite_support/python/task/vision/pybinds:image_embedder_options_pb2", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/__init__.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/__init__.py new file mode 100644 index 0000000..e04127d --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/__init__.py
@@ -0,0 +1,13 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License.
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/BUILD new file mode 100644 index 0000000..f033fab --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/BUILD
@@ -0,0 +1,39 @@ +# Placeholder for internal Python strict test compatibility macro. +# Placeholder for internal Python strict library compatibility macro. + +package( + default_visibility = ["//tensorflow_lite_support:internal"], + licenses = ["notice"], # Apache 2.0 +) + +py_library( + name = "color_space_type", + srcs = ["color_space_type.py"], +) + +py_library( + name = "tensor_image", + srcs = ["tensor_image.py"], + deps = [ + ":color_space_type", + # build rule placeholder: numpy dep, + "//tensorflow_lite_support/python/task/vision/core/pybinds:image_utils", + ], +) + +py_test( + name = "tensor_image_test", + srcs = ["tensor_image_test.py"], + data = [ + "//tensorflow_lite_support/cc/test/testdata/task/vision:test_images", + ], + deps = [ + ":color_space_type", + ":tensor_image", + # build rule placeholder: numpy dep, + # build rule placeholder: tensorflow dep, + "//tensorflow_lite_support/python/task/vision/core/pybinds:image_utils", + "//tensorflow_lite_support/python/test:test_util", + "@absl_py//absl/testing:parameterized", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/__init__.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/__init__.py new file mode 100644 index 0000000..e04127d --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/__init__.py
@@ -0,0 +1,13 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License.
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/color_space_type.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/color_space_type.py new file mode 100644 index 0000000..e4fbd73 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/color_space_type.py
@@ -0,0 +1,28 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Types of color space of an image.""" + +import enum + + +@enum.unique +class ColorSpaceType(enum.Enum): + """Represents the type of color space of an image.""" + # Each pixel is a single element representing only the amount of light. + GRAYSCALE = "GRAYSCALE" + # Each pixel has red, green, and blue color components. + RGB = "RGB" + # An extension of RGB color values with an alpha channel - which specifies the + # opacity of the color. + RGBA = "RGBA"
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/pybinds/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/pybinds/BUILD new file mode 100644 index 0000000..5ef08d5 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/pybinds/BUILD
@@ -0,0 +1,21 @@ +load("@org_tensorflow//tensorflow:tensorflow.bzl", "pybind_extension") + +package( + default_visibility = [ + "//tensorflow_lite_support:internal", + ], + licenses = ["notice"], # Apache 2.0 +) + +pybind_extension( + name = "image_utils", + srcs = [ + "image_utils.cc", + ], + module_name = "image_utils", + deps = [ + "//tensorflow_lite_support/examples/task/vision/desktop/utils:image_utils", + "@pybind11", + "@pybind11_abseil//pybind11_abseil:status_casters", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/tensor_image.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/tensor_image.py new file mode 100644 index 0000000..d354e07 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/tensor_image.py
@@ -0,0 +1,115 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""TensorImage class.""" + +import numpy as np + +from tensorflow_lite_support.python.task.vision.core import color_space_type +from tensorflow_lite_support.python.task.vision.core.pybinds import image_utils + + +class TensorImage(object): + """Wrapper class for the Image object.""" + + def __init__(self, + image_data: image_utils.ImageData, + is_from_file: bool = False) -> None: + """Initializes the `TensorImage` object. + + Args: + image_data: image_utils.ImageData, contains raw image data, width, height + and channels info. + is_from_file: boolean, whether `image_data` is loaded from the image file, + if True, need to free the storage of ImageData in the destructor. + """ + self._image_data = image_data + self._is_from_file = is_from_file + + # Gets the FrameBuffer object. + + @classmethod + def from_file(cls, file_name: str) -> "TensorImage": + """Creates `TensorImage` object from the image file. + + Args: + file_name: Image file name. + + Returns: + `TensorImage` object. + + Raises: + status.StatusNotOk if the image file can't be decoded. Need to import + the module to catch this error: `from pybind11_abseil import status`, + see https://github.com/pybind/pybind11_abseil#abslstatusor. + """ + image_data = image_utils.DecodeImageFromFile(file_name) + return cls(image_data, is_from_file=True) + + @classmethod + def from_array(cls, array: np.ndarray) -> "TensorImage": + """Creates `TensorImage` object from the numpy array. + + Args: + array: numpy array with dtype=uint8. Its shape should be either (h, w, 3) + or (1, h, w, 3) for RGB images, either (h, w) or (1, h, w) for GRAYSCALE + images and either (h, w, 4) or (1, h, w, 4) for RGBA images. + + Returns: + `TensorImage` object. + + Raises: + ValueError if the dytype of the numpy array is not `uint8` or the + dimention is not the valid dimention. + """ + if array.dtype != np.uint8: + raise ValueError("Expect numpy array with dtype=uint8.") + + image_data = image_utils.ImageData(np.squeeze(array)) + return cls(image_data) + + def __del__(self) -> None: + """Destructor to free the storage of ImageData if loaded from the file.""" + if self._is_from_file: + image_utils.ImageDataFree(self._image_data) + + def get_buffer(self) -> np.ndarray: + """Gets the numpy array that represents `self.image_data`. + + Returns: + Numpy array that represents `self.image_data` which is an + `image_util.ImageData` object. To avoid copy, we will use + `return np.array(..., copy = False)`. Therefore, this `TensorImage` + object should out live the returned numpy array. + """ + return np.array(self._image_data, copy=False) + + def get_height(self) -> int: + """Gets the height of the image.""" + return self._image_data.height + + def get_width(self) -> int: + """Gets the width of the image.""" + return self._image_data.width + + def get_color_space_type(self) -> color_space_type.ColorSpaceType: + """Gets the color space type of the image.""" + channels = self._image_data.channels + if channels == 1: + return color_space_type.ColorSpaceType.GRAYSCALE + elif channels == 3: + return color_space_type.ColorSpaceType.RGB + elif channels == 4: + return color_space_type.ColorSpaceType.RGBA + else: + raise ValueError("Unsupported color space type.")
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/tensor_image_test.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/tensor_image_test.py new file mode 100644 index 0000000..56a67795 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/core/tensor_image_test.py
@@ -0,0 +1,58 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for tensor_image.""" + +from absl.testing import parameterized +import numpy as np +import tensorflow as tf + +from tensorflow_lite_support.python.task.vision.core import color_space_type +from tensorflow_lite_support.python.task.vision.core import tensor_image +from tensorflow_lite_support.python.task.vision.core.pybinds import image_utils +from tensorflow_lite_support.python.test import test_util + + +class TensorImageTest(tf.test.TestCase, parameterized.TestCase): + + def test_from_file(self): + image_file = test_util.get_test_data_path('burger.jpg') + image = tensor_image.TensorImage.from_file(image_file) + self.assertIsInstance(image._image_data, image_utils.ImageData) + self.assertEqual(image.get_height(), 325) + self.assertEqual(image.get_width(), 480) + self.assertEqual(image.get_color_space_type(), + color_space_type.ColorSpaceType.RGB) + self.assertIsInstance(image.get_buffer(), np.ndarray) + + @parameterized.parameters( + (1, color_space_type.ColorSpaceType.GRAYSCALE), + (3, color_space_type.ColorSpaceType.RGB), + (4, color_space_type.ColorSpaceType.RGBA), + ) + def test_from_array(self, channels, color_type): + height = 200 + width = 300 + array = np.random.randint( + low=0, high=256, size=(height, width, channels), dtype=np.uint8) + image = tensor_image.TensorImage.from_array(array) + self.assertIsInstance(image._image_data, image_utils.ImageData) + self.assertEqual(image.get_height(), height) + self.assertEqual(image.get_width(), width) + self.assertEqual(image.get_color_space_type(), color_type) + self.assertIsInstance(image.get_buffer(), np.ndarray) + self.assertAllEqual(image.get_buffer(), array) + + +if __name__ == '__main__': + tf.test.main()
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/image_embedder.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/image_embedder.py new file mode 100644 index 0000000..aeda42b1 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/image_embedder.py
@@ -0,0 +1,168 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Image embedder task.""" + +import dataclasses +from typing import Optional + +from tensorflow_lite_support.python.task.core import task_options +from tensorflow_lite_support.python.task.core.proto import configuration_pb2 +from tensorflow_lite_support.python.task.processor.proto import bounding_box_pb2 +from tensorflow_lite_support.python.task.processor.proto import embedding_options_pb2 +from tensorflow_lite_support.python.task.processor.proto import embeddings_pb2 +from tensorflow_lite_support.python.task.vision.core import tensor_image +from tensorflow_lite_support.python.task.vision.core.pybinds import image_utils +from tensorflow_lite_support.python.task.vision.pybinds import _pywrap_image_embedder +from tensorflow_lite_support.python.task.vision.pybinds import image_embedder_options_pb2 + +_ProtoImageEmbedderOptions = image_embedder_options_pb2.ImageEmbedderOptions +_CppImageEmbedder = _pywrap_image_embedder.ImageEmbedder + + +@dataclasses.dataclass +class ImageEmbedderOptions: + """Options for the image embedder task.""" + base_options: task_options.BaseOptions + embedding_options: Optional[embedding_options_pb2.EmbeddingOptions] = None + + +def _build_proto_options( + options: ImageEmbedderOptions) -> _ProtoImageEmbedderOptions: + """Builds the protobuf image embdder options.""" + # Builds the initial proto_options. + proto_options = _ProtoImageEmbedderOptions() + + # Updates values from base_options. + if options.base_options.model_file.file_content: + proto_options.model_file_with_metadata.file_content = ( + options.base_options.model_file.file_content) + elif options.base_options.model_file.file_name: + proto_options.model_file_with_metadata.file_name = ( + options.base_options.model_file.file_name) + + proto_options.num_threads = options.base_options.num_threads + if options.base_options.use_coral: + proto_options.compute_settings.tflite_settings.delegate = ( + configuration_pb2.Delegate.EDGETPU_CORAL) + + # Updates values from embedding_options. + if options.embedding_options: + if options.embedding_options.l2_normalize is not None: + proto_options.l2_normalize = options.embedding_options.l2_normalize + if options.embedding_options.quantize is not None: + proto_options.quantize = options.embedding_options.quantize + + return proto_options + + +class ImageEmbedder(object): + """Class that performs dense feature vector extraction on images.""" + + def __init__(self, embedder: _CppImageEmbedder) -> None: + """Initializes the `ImageEmbedder` object.""" + self._embedder = embedder + + @classmethod + def create_from_options(cls, + options: ImageEmbedderOptions) -> "ImageEmbedder": + """Creates the `ImageEmbedder` object from image embedder options. + + Args: + options: Options for the image embedder task. + + Returns: + `ImageEmbedder` object that's created from `options`. + + Raises: + status.StatusNotOk if failed to create `ImageEmbdder` object from + `ImageEmbedderOptions` such as missing the model. Need to import the + module to catch this error: `from pybind11_abseil import status`, see + https://github.com/pybind/pybind11_abseil#abslstatusor. + """ + # Creates the object of C++ ImageEmbedder class. + proto_options = _build_proto_options(options) + embedder = _CppImageEmbedder.create_from_options(proto_options) + + return cls(embedder) + + def embed( + self, + image: tensor_image.TensorImage, + bounding_box: Optional[bounding_box_pb2.BoundingBox] = None + ) -> embeddings_pb2.EmbeddingResult: + """Performs actual feature vector extraction on the provided TensorImage. + + Args: + image: Tensor image, used to extract the feature vectors. + bounding_box: Bounding box, optional. If set, performed feature vector + extraction only on the provided region of interest. Note that the region + of interest is not clamped, so this method will fail if the region is + out of bounds of the input image. + + Returns: + embedding result. + + Raises: + status.StatusNotOk if failed to get the embedding vector. Need to import + the module to catch this error: `from pybind11_abseil import status`, + see https://github.com/pybind/pybind11_abseil#abslstatusor. + """ + image_data = image_utils.ImageData(image.get_buffer()) + if bounding_box is None: + return self._embedder.embed(image_data) + + return self._embedder.embed(image_data, bounding_box) + + def get_embedding_by_index(self, result: embeddings_pb2.EmbeddingResult, + output_index: int) -> embeddings_pb2.Embedding: + """Gets the embedding in the embedding result by `output_index`. + + Args: + result: embedding result. + output_index: output index of the output layer. + + Returns: + The Embedding output by the output_index'th layer. In (the most common) + case where a single embedding is produced, you can just call + get_feature_vector_by_index(result, 0). + + Raises: + ValueError if the output index is out of bound. + """ + if output_index < 0 or output_index >= len(result.embeddings): + raise ValueError("Output index is out of bound.") + embedding = self._embedder.get_embedding_by_index(result, output_index) + return embedding + + def cosine_similarity(self, u: embeddings_pb2.FeatureVector, + v: embeddings_pb2.FeatureVector) -> float: + """Computes cosine similarity [1] between two feature vectors.""" + return self._embedder.cosine_similarity(u, v) + + def get_embedding_dimension(self, output_index: int) -> int: + """Gets the dimensionality of the embedding output. + + Args: + output_index: The output index of output layer. + + Returns: + Dimensionality of the embedding output by the output_index'th output + layer. Returns -1 if `output_index` is out of bounds. + """ + return self._embedder.get_embedding_dimension(output_index) + + @property + def number_of_output_layers(self) -> int: + """Gets the number of output layers of the model.""" + return self._embedder.get_number_of_output_layers()
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/pybinds/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/pybinds/BUILD new file mode 100644 index 0000000..023001d --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/pybinds/BUILD
@@ -0,0 +1,31 @@ +load("@org_tensorflow//tensorflow:tensorflow.bzl", "pybind_extension") +# Placeholder for internal Python strict library compatibility macro. + +package( + default_visibility = [ + "//tensorflow_lite_support:internal", + ], + licenses = ["notice"], # Apache 2.0 +) + +py_library( + name = "image_embedder_options_pb2", + srcs = ["image_embedder_options_pb2.py"], + deps = ["//tensorflow_lite_support/cc/task/vision/proto:image_embedder_options_py_pb2"], +) + +pybind_extension( + name = "image_embedder", + srcs = [ + "image_embedder.cc", + ], + module_name = "_pywrap_image_embedder", + deps = [ + "//tensorflow_lite_support/cc/port:statusor", + "//tensorflow_lite_support/cc/task/vision:image_embedder", + "//tensorflow_lite_support/examples/task/vision/desktop/utils:image_utils", + "@pybind11", + "@pybind11_abseil//pybind11_abseil:status_casters", + "@pybind11_protobuf//pybind11_protobuf:native_proto_caster", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/pybinds/image_embedder_options_pb2.py b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/pybinds/image_embedder_options_pb2.py new file mode 100644 index 0000000..4cdc513c --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/task/vision/pybinds/image_embedder_options_pb2.py
@@ -0,0 +1,18 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Embedder options protobuf.""" + +from tensorflow_lite_support.cc.task.vision.proto import image_embedder_options_pb2 as embedder_options_pb2 + +ImageEmbedderOptions = embedder_options_pb2.ImageEmbedderOptions
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/test/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/python/test/BUILD new file mode 100644 index 0000000..52b142e0 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/test/BUILD
@@ -0,0 +1,16 @@ +# Placeholder for internal Python strict library compatibility macro. + +package( + default_visibility = ["//tensorflow_lite_support:users"], + licenses = ["notice"], # Apache 2.0 +) + +py_library( + name = "test_util", + testonly = 1, + srcs = ["test_util.py"], + srcs_version = "PY3", + deps = [ + "@absl_py//absl/flags", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/test/task/vision/BUILD b/third_party/tflite_support/src/tensorflow_lite_support/python/test/task/vision/BUILD new file mode 100644 index 0000000..35ab9b4 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/test/task/vision/BUILD
@@ -0,0 +1,27 @@ +# Placeholder for internal Python strict test compatibility macro. + +package( + default_visibility = ["//visibility:private"], + licenses = ["notice"], # Apache 2.0 +) + +py_test( + name = "image_embedder_test", + srcs = ["image_embedder_test.py"], + data = [ + "//tensorflow_lite_support/cc/test/testdata/task/vision:test_images", + "//tensorflow_lite_support/cc/test/testdata/task/vision:test_models", + ], + deps = [ + "//tensorflow_lite_support/python/task/core:task_options", + "//tensorflow_lite_support/python/task/processor/proto:bounding_box_pb2", + "//tensorflow_lite_support/python/task/processor/proto:embedding_options_pb2", + "//tensorflow_lite_support/python/task/processor/proto:embeddings_pb2", + "//tensorflow_lite_support/python/task/vision:image_embedder", + "//tensorflow_lite_support/python/task/vision/core:tensor_image", + "//tensorflow_lite_support/python/test:test_util", + "//testing/pybase", + "@absl_py//absl/testing:parameterized", + "@pybind11_abseil//pybind11_abseil:status", + ], +)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/test/task/vision/image_embedder_test.py b/third_party/tflite_support/src/tensorflow_lite_support/python/test/task/vision/image_embedder_test.py new file mode 100644 index 0000000..98c45b6 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/test/task/vision/image_embedder_test.py
@@ -0,0 +1,179 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Tests for image_embedder.""" + +import enum + +from absl.testing import parameterized + +from tensorflow_lite_support.python.task.core import task_options +from tensorflow_lite_support.python.task.processor.proto import bounding_box_pb2 +from tensorflow_lite_support.python.task.processor.proto import embedding_options_pb2 +from tensorflow_lite_support.python.task.processor.proto import embeddings_pb2 +from tensorflow_lite_support.python.task.vision import image_embedder +from tensorflow_lite_support.python.task.vision.core import tensor_image +from tensorflow_lite_support.python.test import test_util +import unittest + +_BaseOptions = task_options.BaseOptions +_ExternalFile = task_options.ExternalFile +_ImageEmbedder = image_embedder.ImageEmbedder +_ImageEmbedderOptions = image_embedder.ImageEmbedderOptions + + +class ModelFileType(enum.Enum): + FILE_CONTENT = 1 + FILE_NAME = 2 + + +class ImageEmbedderTest(parameterized.TestCase, unittest.TestCase): + + def setUp(self): + super().setUp() + self.model_path = test_util.get_test_data_path( + "mobilenet_v3_small_100_224_embedder.tflite") + + def test_create_from_options_succeeds_with_valid_model_path(self): + # Creates with options containing model file successfully. + base_options = _BaseOptions( + model_file=_ExternalFile(file_name=self.model_path)) + options = _ImageEmbedderOptions(base_options=base_options) + embedder = _ImageEmbedder.create_from_options(options) + self.assertIsInstance(embedder, _ImageEmbedder) + + def test_create_from_options_fails_with_missing_model_file(self): + # Missing the model file. + with self.assertRaisesRegex( + TypeError, + r"__init__\(\) missing 1 required positional argument: 'model_file'"): + _BaseOptions() + + def test_create_from_options_fails_with_invalid_model_path(self): + # Invalid empty model path. + with self.assertRaisesRegex( + Exception, + r"INVALID_ARGUMENT: ExternalFile must specify at least one of " + r"'file_content', file_name' or 'file_descriptor_meta'\. " + r"\[tflite::support::TfLiteSupportStatus='2'\]"): + base_options = _BaseOptions(model_file=_ExternalFile(file_name="")) + options = _ImageEmbedderOptions(base_options=base_options) + _ImageEmbedder.create_from_options(options) + + def test_create_from_options_succeeds_with_valid_model_content(self): + # Creates with options containing model content successfully. + with open(self.model_path, "rb") as f: + base_options = _BaseOptions( + model_file=_ExternalFile(file_content=f.read())) + options = _ImageEmbedderOptions(base_options=base_options) + embedder = _ImageEmbedder.create_from_options(options) + self.assertIsInstance(embedder, _ImageEmbedder) + + @parameterized.parameters( + (False, False, False, ModelFileType.FILE_NAME, 0.932738), + (True, False, False, ModelFileType.FILE_NAME, 0.932738), + (True, True, False, ModelFileType.FILE_CONTENT, 0.929717), + (False, False, True, ModelFileType.FILE_CONTENT, 0.999914), + ) + def test_embed(self, l2_normalize, quantize, with_bounding_box, + model_file_type, expected_similarity): + # Creates embedder. + if model_file_type is ModelFileType.FILE_NAME: + model_file = _ExternalFile(file_name=self.model_path) + elif model_file_type is ModelFileType.FILE_CONTENT: + with open(self.model_path, "rb") as f: + model_content = f.read() + model_file = _ExternalFile(file_content=model_content) + else: + # Should never happen + raise ValueError("model_file_type is invalid.") + + base_options = _BaseOptions(model_file) + embedding_options = embedding_options_pb2.EmbeddingOptions( + l2_normalize=l2_normalize, quantize=quantize) + options = _ImageEmbedderOptions( + base_options=base_options, embedding_options=embedding_options) + embedder = _ImageEmbedder.create_from_options(options) + + # Loads images: one is a crop of the other. + image = tensor_image.TensorImage.from_file( + test_util.get_test_data_path("burger.jpg")) + cropped_image = tensor_image.TensorImage.from_file( + test_util.get_test_data_path("burger_crop.jpg")) + + bounding_box = None + if with_bounding_box: + # Bounding box in "burger.jpg" corresponding to "burger_crop.jpg". + bounding_box = bounding_box_pb2.BoundingBox( + origin_x=0, origin_y=0, width=400, height=325) + + # Extracts both embeddings. + image_result = embedder.embed(image, bounding_box) + crop_result = embedder.embed(cropped_image) + + # Checks results sizes. + self.assertLen(image_result.embeddings, 1) + image_feature_vector = image_result.embeddings[0].feature_vector + self.assertLen(crop_result.embeddings, 1) + crop_feature_vector = crop_result.embeddings[0].feature_vector + if quantize: + self.assertLen(image_feature_vector.value_string, 1024) + self.assertLen(crop_feature_vector.value_string, 1024) + else: + self.assertLen(image_feature_vector.value_float, 1024) + self.assertLen(crop_feature_vector.value_float, 1024) + + # Checks cosine similarity. + similarity = embedder.cosine_similarity(image_feature_vector, + crop_feature_vector) + self.assertAlmostEqual(similarity, expected_similarity, places=6) + + def test_get_embedding_by_index(self): + base_options = _BaseOptions( + model_file=_ExternalFile(file_name=self.model_path)) + options = _ImageEmbedderOptions(base_options=base_options) + embedder = _ImageEmbedder.create_from_options(options) + + # Builds test data. + embedding = embeddings_pb2.Embedding(output_index=0) + embedding.feature_vector.value_float.append(1.0) + embedding.feature_vector.value_float.append(0.0) + embedding_result = embeddings_pb2.EmbeddingResult() + embedding_result.embeddings.append(embedding) + + result0 = embedder.get_embedding_by_index(embedding_result, 0) + self.assertEqual(result0.output_index, 0) + self.assertEqual(result0.feature_vector.value_float[0], 1.0) + self.assertEqual(result0.feature_vector.value_float[1], 0.0) + + with self.assertRaisesRegex(ValueError, r"Output index is out of bound\."): + embedder.get_embedding_by_index(embedding_result, 1) + + def test_get_embedding_dimension(self): + base_options = _BaseOptions( + model_file=_ExternalFile(file_name=self.model_path)) + options = _ImageEmbedderOptions(base_options=base_options) + embedder = _ImageEmbedder.create_from_options(options) + self.assertEqual(embedder.get_embedding_dimension(0), 1024) + self.assertEqual(embedder.get_embedding_dimension(1), -1) + + def test_number_of_output_layers(self): + base_options = _BaseOptions( + model_file=_ExternalFile(file_name=self.model_path)) + options = _ImageEmbedderOptions(base_options=base_options) + embedder = _ImageEmbedder.create_from_options(options) + self.assertEqual(embedder.number_of_output_layers, 1) + + +if __name__ == "__main__": + unittest.main()
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/python/test/test_util.py b/third_party/tflite_support/src/tensorflow_lite_support/python/test/test_util.py new file mode 100644 index 0000000..526f68f2 --- /dev/null +++ b/third_party/tflite_support/src/tensorflow_lite_support/python/test/test_util.py
@@ -0,0 +1,38 @@ +# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +"""Test util for tensorflow lite support.""" + +import os +from absl import flags + +FLAGS = flags.FLAGS + + +def test_srcdir(): + """Returns the path where to look for test data files.""" + if "test_srcdir" in flags.FLAGS: + return flags.FLAGS["test_srcdir"].value + elif "TEST_SRCDIR" in os.environ: + return os.environ["TEST_SRCDIR"] + else: + raise RuntimeError("Missing TEST_SRCDIR environment.") + + +def get_test_data_path(file_or_dirname: str) -> str: + """Return full test data path.""" + for (directory, subdirs, files) in os.walk(test_srcdir()): + for f in subdirs + files: + if f.endswith(file_or_dirname): + return os.path.join(directory, f) + raise ValueError("No %s in test directory" % file_or_dirname)
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common.sh b/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common.sh index 4907bb1b..17c38d2 100755 --- a/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common.sh +++ b/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common.sh
@@ -1,96 +1,90 @@ -#!/usr/bin/env bash -# Copyright 2020 The TensorFlow Authors. All Rights Reserved. +#!/ usr / bin / env bash +#Copyright 2020 The TensorFlow Authors.All Rights Reserved. # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +#Licensed under the Apache License, Version 2.0(the "License"); +#you may not use this file except in compliance with the License. +#You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +#http: // www.apache.org/licenses/LICENSE-2.0 # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== -# External `common.sh` +#Unless required by applicable law or agreed to in writing, software +#distributed under the License is distributed on an "AS IS" BASIS, +#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#See the License for the specific language governing permissions and +#limitations under the License. +#== == == == == == == == == == == == == == == == == == == == == == == == == == \ + == == == == == == == == == == == == == +#External `common.sh` -# Keep in sync with tensorflow core and configure.py. -# TODO(b/158448780): Guard bazel version with IfChangeThenChange. -LATEST_BAZEL_VERSION=3.1.0 - -# Run flaky functions with retries. -# run_with_retry cmd -function run_with_retry { +#Keep in sync with tensorflow core and configure.py. +LATEST_BAZEL_VERSION = 4.2.2 +#Run flaky functions with retries. +#run_with_retry cmd + function run_with_retry { eval "$1" - # If the command fails retry again in 60 seconds. - if [[ $? -ne 0 ]]; then - sleep 60 - eval "$1" - fi +#If the command fails retry again in 60 seconds. + if [[ $? -ne 0 ]]; + then sleep 60 eval "$1" fi } function die() { - echo "$@" 1>&2 ; exit 1; + echo "$@" 1 > &2; + exit 1; } -# A small utility to run the command and only print logs if the command fails. -# On success, all logs are hidden. -function readable_run { - # Disable debug mode to avoid printing of variables here. - set +x - result=$("$@" 2>&1) || die "$result" - echo "$@" - echo "Command completed successfully at $(date)" - set -x -} +#A small utility to run the command and only print logs if the command fails. +#On success, all logs are hidden. +function readable_run{ +#Disable debug mode to avoid printing of variables here. + set + x result = + $("$@" 2 > &1) || die "$result" echo "$@" echo + "Command completed successfully at $(date)" set - + x} -# TODO(b/158448780): Guard bazel installation with IfChangeThenChange. -function set_bazel_outdir { - mkdir -p /tmpfs/bazel_output - export TEST_TMPDIR=/tmpfs/bazel_output -} +#TODO(b / 158448780) : Guard bazel installation with IfChangeThenChange. +function set_bazel_outdir{mkdir - p / tmpfs / bazel_output export TEST_TMPDIR = + / tmpfs / bazel_output} -# Downloads bazelisk to ~/bin as `bazel`. +#Downloads bazelisk to ~ / bin as `bazel`. function install_bazelisk { date case "$(uname -s)" in - Darwin) local name=bazelisk-darwin-amd64 ;; - Linux) local name=bazelisk-linux-amd64 ;; - *) die "Unknown OS: $(uname -s)" ;; - esac - mkdir -p "$HOME/bin" - wget --no-verbose -O "$HOME/bin/bazel" \ - "https://github.com/bazelbuild/bazelisk/releases/download/v1.3.0/$name" - chmod u+x "$HOME/bin/bazel" - if [[ ! ":$PATH:" =~ :"$HOME"/bin/?: ]]; then - PATH="$HOME/bin:$PATH" - fi - set_bazel_outdir - which bazel - bazel version - date + Darwin) local name=bazelisk-darwin-amd64 ; + ; + Linux) local name=bazelisk-linux-amd64 ; + ; + *) die "Unknown OS: $(uname -s)" ; + ; + esac mkdir - p "$HOME/bin" wget-- no - verbose - + O + "$HOME/bin/bazel" + "https://github.com/bazelbuild/bazelisk/releases/download/v1.3.0/" + "$name" chmod u + + x "$HOME/bin/bazel" if[[!":$PATH:" = ~:"$HOME" / bin / ?: ]]; + then PATH = + "$HOME/bin:$PATH" fi set_bazel_outdir which bazel bazel version date } -# Install the given bazel version on linux +#Install the given bazel version on linux function update_bazel_linux { - if [[ -z "$1" ]]; then - BAZEL_VERSION=${LATEST_BAZEL_VERSION} - else - BAZEL_VERSION=$1 - fi - rm -rf ~/bazel - mkdir ~/bazel + if + [[-z "$1"]]; + then BAZEL_VERSION = $ { + LATEST_BAZEL_VERSION + } + else BAZEL_VERSION = + $1 fi rm - + rf ~ / bazel mkdir ~ / + bazel - pushd ~/bazel - readable_run wget https://github.com/bazelbuild/bazel/releases/download/"${BAZEL_VERSION}"/bazel-"${BAZEL_VERSION}"-installer-linux-x86_64.sh - chmod +x bazel-*.sh - ./bazel-"${BAZEL_VERSION}"-installer-linux-x86_64.sh --user - rm bazel-"${BAZEL_VERSION}"-installer-linux-x86_64.sh - popd + pushd ~ / + bazel readable_run wget https + : // github.com/bazelbuild/bazel/releases/download/"${BAZEL_VERSION}"/bazel-"${BAZEL_VERSION}"-installer-linux-x86_64.sh + chmod + + x bazel - *.sh./ bazel - "${BAZEL_VERSION}" - installer - linux - + x86_64.sh-- user rm bazel - "${BAZEL_VERSION}" - installer - linux - + x86_64.sh popd - PATH="/home/kbuilder/bin:$PATH" - set_bazel_outdir - which bazel - bazel version + PATH = + "/home/kbuilder/bin:$PATH" set_bazel_outdir which bazel bazel version }
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common_win.bat b/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common_win.bat index 702fb89f..324a195 100755 --- a/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common_win.bat +++ b/third_party/tflite_support/src/tensorflow_lite_support/tools/ci_build/common_win.bat
@@ -22,7 +22,7 @@ @REM Setup Bazel @REM :: Download Bazel from github and make sure its found in PATH. -SET BAZEL_VERSION=3.7.2 +SET BAZEL_VERSION=4.2.2 md C:\tools\bazel\ wget -q https://github.com/bazelbuild/bazel/releases/download/%BAZEL_VERSION%/bazel-%BAZEL_VERSION%-windows-x86_64.exe -O C:/tools/bazel/bazel.exe SET PATH=C:\tools\bazel;%PATH%
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/Makefile b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/Makefile index 31d600b..3e5705e 100644 --- a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/Makefile +++ b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/Makefile
@@ -16,6 +16,9 @@ BASE_IMAGE ?= ubuntu:16.04 PYTHON_VERSION ?= 3.9 +# Nightly flag for build_arm_pip_package.sh +NIGHLTY_FLAG ?= --nightly_flag + MAKEFILE_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) WORKSPACE_DIR := $(MAKEFILE_DIR)/../../../.. TAG_IMAGE := "tflite-runtime-builder-$(subst :,-,$(BASE_IMAGE))" @@ -57,7 +60,7 @@ --rm --interactive $(shell tty -s && echo --tty) \ $(DOCKER_PARAMS) \ $(TAG_IMAGE) \ - /with_the_same_user /bin/bash -C tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh + /with_the_same_user /bin/bash -C tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh $(NIGHLTY_FLAG) clean: rm -rf $(CURDIR)/wheels
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh index 9676de41..e2ad7ac 100755 --- a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh +++ b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/build_arm_pip_package.sh
@@ -1,22 +1,37 @@ -#!/usr/bin/env bash -# Copyright 2021 The TensorFlow Authors. All Rights Reserved. +#!/ usr / bin / env bash +#Copyright 2021 The TensorFlow Authors.All Rights Reserved. # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +#Licensed under the Apache License, Version 2.0(the "License"); +#you may not use this file except in compliance with the License. +#You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +#http: // www.apache.org/licenses/LICENSE-2.0 # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== +#Unless required by applicable law or agreed to in writing, software +#distributed under the License is distributed on an "AS IS" BASIS, +#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#See the License for the specific language governing permissions and +#limitations under the License. +#== == == == == == == == == == == == == == == == == == == == == == == == == == \ + == == == == == == == == == == == == == -set -ex +set - ex -bazel build -c opt --config=elinux_armhf tensorflow_lite_support/tools/pip_package:build_pip_package -EXTRA_PKG_NAME_FLAG="--plat-name=manylinux2014-armv7l" ./bazel-bin/tensorflow_lite_support/tools/pip_package/build_pip_package --dst wheels --nightly_flag -bazel build -c opt --config=elinux_aarch64 tensorflow_lite_support/tools/pip_package:build_pip_package -EXTRA_PKG_NAME_FLAG="--plat-name=manylinux2014-aarch64" ./bazel-bin/tensorflow_lite_support/tools/pip_package/build_pip_package --dst wheels --nightly_flag + NIGHTLY_FLAG = + $1 + + bazel build - + c opt-- config = + elinux_armhf tensorflow_lite_support / tools / + pip_package : build_pip_package EXTRA_PKG_NAME_FLAG = + "--plat-name=manylinux2014-armv7l"./ bazel - + bin / tensorflow_lite_support / tools / pip_package / + build_pip_package-- dst wheels ${NIGHTLY_FLAG} bazel build - + c opt-- config = + elinux_aarch64 tensorflow_lite_support / tools / + pip_package : build_pip_package EXTRA_PKG_NAME_FLAG = + "--plat-name=manylinux2014-aarch64"./ bazel - + bin / tensorflow_lite_support / tools / pip_package / + build_pip_package-- dst wheels $ { + NIGHTLY_FLAG +}
diff --git a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh index 063e1f9..fd376bf8 100755 --- a/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh +++ b/third_party/tflite_support/src/tensorflow_lite_support/tools/pip_package/rpi/install_bazel.sh
@@ -1,40 +1,53 @@ -#!/usr/bin/env bash -# Copyright 2015 The TensorFlow Authors. All Rights Reserved. +#!/ usr / bin / env bash +#Copyright 2015 The TensorFlow Authors.All Rights Reserved. # -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at +#Licensed under the Apache License, Version 2.0(the "License"); +#you may not use this file except in compliance with the License. +#You may obtain a copy of the License at # -# http://www.apache.org/licenses/LICENSE-2.0 +#http: // www.apache.org/licenses/LICENSE-2.0 # -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ============================================================================== +#Unless required by applicable law or agreed to in writing, software +#distributed under the License is distributed on an "AS IS" BASIS, +#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +#See the License for the specific language governing permissions and +#limitations under the License. +#== == == == == == == == == == == == == == == == == == == == == == == == == == \ + == == == == == == == == == == == == == -# Select bazel version. -BAZEL_VERSION="3.7.2" +#Select bazel version. +BAZEL_VERSION = "4.2.2" -set +e -local_bazel_ver=$(bazel version 2>&1 | grep -i label | awk '{print $3}') + set + + e local_bazel_ver = + $(bazel version 2 > &1 | grep - i label | awk '{print $3}') -if [[ "$local_bazel_ver" == "$BAZEL_VERSION" ]]; then - exit 0 -fi + if[["$local_bazel_ver" == "$BAZEL_VERSION"]]; +then exit 0 fi -set -e + set - + e -# Install bazel. -mkdir -p /bazel -cd /bazel -if [[ ! -f "bazel-$BAZEL_VERSION-installer-linux-x86_64.sh" ]]; then - curl -fSsL -O https://github.com/bazelbuild/bazel/releases/download/$BAZEL_VERSION/bazel-$BAZEL_VERSION-installer-linux-x86_64.sh -fi -chmod +x /bazel/bazel-*.sh -/bazel/bazel-$BAZEL_VERSION-installer-linux-x86_64.sh -rm -f /bazel/bazel-$BAZEL_VERSION-installer-linux-x86_64.sh +#Install bazel. + mkdir - + p / bazel cd / + bazel if[[!-f "bazel-$BAZEL_VERSION-installer-linux-x86_64.sh"]]; +then curl - fSsL - + O https + : // github.com/bazelbuild/bazel/releases/download/$BAZEL_VERSION/bazel-$BAZEL_VERSION-installer-linux-x86_64.sh + fi chmod + + x / bazel / bazel - + *.sh / bazel / bazel - + $BAZEL_VERSION - + installer - + linux - + x86_64.sh rm - + f / bazel / bazel - + $BAZEL_VERSION - + installer - + linux - + x86_64.sh -# Enable bazel auto completion. -echo "source /usr/local/lib/bazel/bin/bazel-complete.bash" >> ~/.bashrc +#Enable bazel auto completion. + echo "source /usr/local/lib/bazel/bin/bazel-complete.bash" >> + ~ /.bashrc
diff --git a/third_party/tflite_support/src/third_party/pybind11_protobuf/BUILD b/third_party/tflite_support/src/third_party/pybind11_protobuf/BUILD new file mode 100644 index 0000000..82bab3f --- /dev/null +++ b/third_party/tflite_support/src/third_party/pybind11_protobuf/BUILD
@@ -0,0 +1 @@ +# This empty BUILD file is required to make Bazel treat this directory as a package.
diff --git a/third_party/tflite_support/src/third_party/pybind11_protobuf/com_google_protobuf_build.patch b/third_party/tflite_support/src/third_party/pybind11_protobuf/com_google_protobuf_build.patch new file mode 100644 index 0000000..6053378 --- /dev/null +++ b/third_party/tflite_support/src/third_party/pybind11_protobuf/com_google_protobuf_build.patch
@@ -0,0 +1,11 @@ +-- -BUILD++ + BUILD @ @-889, 6 + 889, + 8 @@ + "//conditions:default" : [], + ":use_fast_cpp_protos" + : ["//external:python_headers"], +}), ++ ++ visibility = ["//visibility:public"], + ) + + config_setting(
diff --git a/tools/android/build_speed/benchmark.py b/tools/android/build_speed/benchmark.py index 820cfe01..f9da146 100755 --- a/tools/android/build_speed/benchmark.py +++ b/tools/android/build_speed/benchmark.py
@@ -420,9 +420,9 @@ use_emulator: bool) -> Iterator[Tuple[str, List[float]]]: out_dir = os.path.relpath(output_directory, _SRC_ROOT) args_gn_path = os.path.join(out_dir, 'args.gn') - emulator_ctx = _emulator() if use_emulator else contextlib.nullcontext() - server_ctx = _server() if not no_server else contextlib.nullcontext() - with _backup_file(args_gn_path), server_ctx, emulator_ctx as emulator: + emulator_ctx = _emulator if use_emulator else contextlib.nullcontext + server_ctx = _server if not no_server else contextlib.nullcontext + with _backup_file(args_gn_path), emulator_ctx() as emulator: with open(args_gn_path, 'w') as f: # Use newlines instead of spaces since autoninja.py uses regex to # determine whether use_goma is turned on or off. @@ -433,12 +433,16 @@ time_taken = [] for run_num in range(repeat): logging.info(f'Run number: {run_num + 1}') - for elapsed in _run_benchmark(out_dir=out_dir, - target=target, - emulator=emulator, - **benchmark.info): - logging.info(f'Time: {elapsed:.1f}s') - time_taken.append(elapsed) + # Run the fast local dev server fresh for each benchmark run + # to avoid later benchmarks being slower due to the server + # accumulating queued tasks. + with server_ctx(): + for elapsed in _run_benchmark(out_dir=out_dir, + target=target, + emulator=emulator, + **benchmark.info): + logging.info(f'Time: {elapsed:.1f}s') + time_taken.append(elapsed) logging.info(f'Completed {benchmark.name}') logging.info('Result: %s', _format_result(time_taken)) yield benchmark.name, time_taken
diff --git a/tools/attribution_reporting/BUILD.gn b/tools/attribution_reporting/BUILD.gn index 1850b9e..59b28f3 100644 --- a/tools/attribution_reporting/BUILD.gn +++ b/tools/attribution_reporting/BUILD.gn
@@ -7,6 +7,7 @@ deps = [ "//base", "//components/version_info", + "//content/public/browser", "//content/test:test_support", ] testonly = true
diff --git a/tools/attribution_reporting/DEPS b/tools/attribution_reporting/DEPS index 40017b0..9d1cfc2 100644 --- a/tools/attribution_reporting/DEPS +++ b/tools/attribution_reporting/DEPS
@@ -1,4 +1,5 @@ include_rules = [ "+components/version_info", + "+content/public/browser", "+content/public/test", ]
diff --git a/tools/attribution_reporting/simulator_main.cc b/tools/attribution_reporting/simulator_main.cc index 491b3aa..e9cb5cb4 100644 --- a/tools/attribution_reporting/simulator_main.cc +++ b/tools/attribution_reporting/simulator_main.cc
@@ -2,16 +2,20 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include <fstream> #include <iostream> #include <string> #include "base/command_line.h" #include "base/containers/contains.h" #include "base/files/file_path.h" -#include "base/json/json_file_value_serializer.h" +#include "base/files/file_util.h" +#include "base/json/json_string_value_serializer.h" #include "base/json/json_writer.h" +#include "base/test/test_timeouts.h" #include "base/values.h" #include "components/version_info/version_info.h" +#include "content/public/browser/attribution_reporting.h" #include "content/public/test/attribution_simulator.h" namespace { @@ -22,14 +26,19 @@ constexpr char kSwitchVersion[] = "version"; constexpr char kSwitchVersionShort[] = "v"; +constexpr char kSwitchDelayMode[] = "delay_mode"; constexpr char kSwitchInputFile[] = "input_file"; +constexpr char kSwitchNoiseMode[] = "noise_mode"; constexpr char kSwitchRemoveReportIds[] = "remove_report_ids"; +constexpr char kSwitchInputMode[] = "input_mode"; constexpr const char* kAllowedSwitches[] = { kSwitchHelp, kSwitchHelpShort, kSwitchVersion, kSwitchVersionShort, - kSwitchInputFile, kSwitchRemoveReportIds, + kSwitchInputFile, kSwitchDelayMode, + kSwitchNoiseMode, kSwitchRemoveReportIds, + kSwitchInputMode, }; constexpr const char* kRequiredSwitches[] = { @@ -38,12 +47,15 @@ constexpr char kHelpMsg[] = R"( attribution_reporting_simulator --input_file=<input_file> + [--delay_mode=<mode>] + [--noise_mode=<mode>] + [--input_mode=<input_mode>] [--remove_report_ids] attribution_reporting_simulator is a command-line tool that simulates the -Attribution Reporting API for a single user on sources and triggers specified -in an input file. It writes the generated reports, if any, to stdout, with -associated metadata. +Attribution Reporting API for for sources and triggers specified in an input +file. It writes the generated reports, if any, to stdout, with associated +metadata. Sources and triggers are registered in chronological order according to their `source_time` and `trigger_time` fields, respectively. @@ -55,9 +67,39 @@ https://github.com/WICG/conversion-measurement-api/blob/main/EVENT.md. Switches: - --input_file=<input_file> - Required path to a JSON file containing sources + --input_file=<input_file> - Required path to an input file containing sources and triggers to register in the simulation. Input format described below. + + --delay_mode=<mode> - Optional. One of `default` or `none`. Defaults to + `default`. + + default: Reports are sent in reporting windows + some time after attribution is triggered. + + none: Reports are sent immediately after + attribution is triggered. + + --noise_mode=<mode> - Optional. One of `default` or `none`. Defaults to + `default`. + + default: Sources are subject to randomized + response, reports within a reporting window are + shuffled. + + none: None of the above applies. + + --input_mode=<input_mode> - Optional. Either `single` (default) or `multi`. + single: the input file must conform to the JSON + input format below. Output will conform to the + JSON output below. + multi: Each line in the input file must + conform to the input format below. Each output + line will conform to the JSON output format. + Input lines are processed independently, + simulating multiple users. + See https://jsonlines.org/. + --remove_report_ids - Optional. If present, removes the `report_id` field from report bodies, as they are randomly generated. Use this switch to make the tool's @@ -65,7 +107,7 @@ --version - Outputs the tool version and exits. -Input format: +Input JSON format: { // List of zero or more sources to register. @@ -140,7 +182,7 @@ ] } -Output format: +Output JSON format: { // List of zero or more reports. @@ -164,10 +206,34 @@ } )"; +enum class InputMode { kSingle, kMulti }; + void PrintHelp() { std::cerr << kHelpMsg; } +int ProcessJsonString(const std::string& json_input, + const content::AttributionSimulationOptions& options, + int json_write_options) { + std::string error_msg; + std::unique_ptr<base::Value> input = + JSONStringValueDeserializer(json_input).Deserialize(nullptr, &error_msg); + if (!input) { + std::cerr << "failed to deserialize input: " << error_msg << std::endl; + return 1; + } + base::Value output = content::RunAttributionSimulationOrExit(*input, options); + std::string output_json; + bool success = base::JSONWriter::WriteWithOptions(output, json_write_options, + &output_json); + if (!success) { + std::cerr << "failed to serialize output JSON" << std::endl; + return 1; + } + std::cout << output_json; + return 0; +} + } // namespace int main(int argc, char* argv[]) { @@ -212,30 +278,80 @@ } } - std::string error_msg; - std::unique_ptr<base::Value> input = - JSONFileValueDeserializer( - command_line.GetSwitchValuePath(kSwitchInputFile)) - .Deserialize(nullptr, &error_msg); - if (!input) { - std::cerr << "failed to read input file: " << error_msg << std::endl; - return 1; + auto noise_mode = content::AttributionNoiseMode::kDefault; + if (command_line.HasSwitch(kSwitchNoiseMode)) { + std::string str = command_line.GetSwitchValueASCII(kSwitchNoiseMode); + + if (str == "none") { + noise_mode = content::AttributionNoiseMode::kNone; + } else if (str != "default") { + std::cerr << "unknown noise mode: " << str << std::endl; + return 1; + } } - base::Value output = content::RunAttributionSimulationOrExit( - *input, - content::AttributionSimulationOptions{ - .remove_report_ids = command_line.HasSwitch(kSwitchRemoveReportIds), - }); + auto delay_mode = content::AttributionDelayMode::kDefault; + if (command_line.HasSwitch(kSwitchDelayMode)) { + std::string str = command_line.GetSwitchValueASCII(kSwitchDelayMode); - std::string output_json; - bool success = base::JSONWriter::WriteWithOptions( - output, base::JSONWriter::OPTIONS_PRETTY_PRINT, &output_json); - if (!success) { - std::cerr << "failed to serialize output JSON"; - return 1; + if (str == "none") { + delay_mode = content::AttributionDelayMode::kNone; + } else if (str != "default") { + std::cerr << "unknown report mode: " << str << std::endl; + return 1; + } } - std::cout << output_json; - return 0; + auto input_mode = InputMode::kSingle; + if (command_line.HasSwitch(kSwitchInputMode)) { + std::string input_mode_string = + command_line.GetSwitchValueASCII(kSwitchInputMode); + if (input_mode_string == "multi") { + input_mode = InputMode::kMulti; + } else if (input_mode_string != "single") { + std::cerr << "bad input_mode encountered: `" << input_mode_string << "`" + << std::endl; + PrintHelp(); + return 1; + } + } + + content::AttributionSimulationOptions options({ + .noise_mode = noise_mode, + .delay_mode = delay_mode, + .remove_report_ids = command_line.HasSwitch(kSwitchRemoveReportIds), + }); + + // Required for using mock time in the simulator. Must be initialized exactly + // once. + TestTimeouts::Initialize(); + + switch (input_mode) { + case InputMode::kSingle: { + std::string input_string; + bool success = base::ReadFileToString( + command_line.GetSwitchValuePath(kSwitchInputFile), &input_string); + if (!success) { + std::cerr << "failed to read input file." << std::endl; + return 1; + } + return ProcessJsonString(input_string, options, + base::JSONWriter::OPTIONS_PRETTY_PRINT); + } + case InputMode::kMulti: { + // TODO(csharrison): use base::File if a ReadLine helper ever exists. + std::string line; + std::ifstream input(command_line.GetSwitchValueASCII(kSwitchInputFile)); + if (!input.good()) { + std::cerr << "failed to read input file." << std::endl; + return 1; + } + int ret = 0; + while (std::getline(input, line) && ret == 0) { + ret = ProcessJsonString(line, options, 0); + std::cout << std::endl; + } + return ret; + } + } }
diff --git a/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt b/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt index 269080d..38798c7 100644 --- a/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt +++ b/tools/clang/rewrite_raw_ptr_fields/manual-fields-to-ignore.txt
@@ -361,6 +361,8 @@ mojo::internal::MayAutoUnlock::lock_ mojo::internal::MultiplexRouter::header_validator_ url::CanonOutputT::buffer_ +prefs::ScopedDictionaryPrefUpdate::service_ +prefs::DictionaryValueUpdate::value_ # Populated manually - type is unsupported by raw_ptr to avoid being used in # performance sensitive base::Unretained
diff --git a/tools/gritsettings/resource_ids.spec b/tools/gritsettings/resource_ids.spec index c53c9d7c..1d97c3c 100644 --- a/tools/gritsettings/resource_ids.spec +++ b/tools/gritsettings/resource_ids.spec
@@ -395,6 +395,10 @@ "content/dev_ui_content_resources.grd": { "includes": [2620], }, + "<(SHARED_INTERMEDIATE_DIR)/chrome/browser/resources/feed/resources.grd": { + "META": {"sizes": {"includes": [20]}}, + "includes": [2640], + }, # END chrome/ WebUI resources section # START chrome/ miscellaneous section.
diff --git a/tools/mb/mb_config.pyl b/tools/mb/mb_config.pyl index 08f63c7..195971a 100644 --- a/tools/mb/mb_config.pyl +++ b/tools/mb/mb_config.pyl
@@ -789,6 +789,7 @@ 'tryserver.chromium.android': { 'android-asan': 'android_clang_asan_release_trybot', 'android-bfcache-rel': 'android_release_trybot', + 'android-clang-tidy-rel': 'android_release_trybot', 'android-opus-arm-rel': 'android_release_trybot', 'android-cronet-asan-arm-rel': 'android_cronet_release_bot_minimal_symbols_arm_no_neon_clang_asan', # TODO(crbug/597596): Switch this back to debug_trybot when cronet's @@ -947,10 +948,12 @@ 'lacros-arm-generic-rel': 'chromeos_arm-generic_lacros_rel_dchecks', 'linux-chromeos-inverse-fieldtrials-fyi-rel': 'chromeos_with_codecs_release_trybot_invert_fieldtrials', 'linux-chromeos-annotator-rel': 'chromeos_with_codecs_release_trybot_code_coverage', + 'linux-chromeos-clang-tidy-rel': 'chromeos_with_codecs_release_trybot', 'linux-chromeos-rel': 'chromeos_with_codecs_release_trybot_code_coverage', 'linux-chromeos-js-code-coverage': 'chromeos_with_codecs_release_trybot_js_cpp_code_coverage', 'linux-chromeos-compile-dbg': 'chromeos_with_codecs_debug_bot', 'linux-chromeos-dbg': 'chromeos_with_codecs_debug_bot', + 'linux-lacros-clang-tidy-rel': 'lacros_on_linux_release_trybot', 'linux-lacros-dbg': 'lacros_on_linux_debug_bot', 'linux-lacros-rel': 'lacros_on_linux_release_trybot', 'linux-lacros-rel-code-coverage': 'lacros_on_linux_release_trybot_coverage', @@ -991,6 +994,7 @@ 'fuchsia_arm64': 'release_trybot_fuchsia_arm64', 'fuchsia-arm64-cast': 'release_trybot_fuchsia_arm64_cast', 'fuchsia-binary-size': 'release_fuchsia_arm64', + 'fuchsia-clang-tidy-rel': 'release_trybot_fuchsia', 'fuchsia-compile-x64-dbg': 'debug_bot_fuchsia_compile_only', 'fuchsia-deterministic-dbg': 'debug_bot_fuchsia', 'fuchsia-fyi-arm64-dbg': 'debug_bot_fuchsia_arm64', @@ -1110,6 +1114,7 @@ 'ios14-sdk-simulator': 'ios_simulator_debug_static_bot_xctest_arm64', 'ios15-beta-simulator': 'ios_simulator_debug_static_bot_xctest', 'ios15-sdk-simulator': 'ios_simulator_debug_static_bot_xctest', + 'ios-clang-tidy-rel': 'ios_device_release_compile_only', 'ios-simulator': 'ios_simulator_code_coverage_partial_instrumentation_xctest', 'ios-simulator-full-configs': 'ios_simulator_code_coverage_partial_instrumentation_xctest', 'ios-simulator-cronet': 'ios_cronet_xctest', @@ -1130,6 +1135,7 @@ 'mac_chromium_compile_dbg_ng': 'gpu_tests_debug_bot', 'mac_chromium_compile_rel_ng': 'gpu_tests_release_trybot', 'mac_chromium_dbg_ng': 'gpu_tests_debug_bot', + 'mac-clang-tidy-rel': 'release_trybot', 'mac_optional_gpu_tests_rel': 'gpu_fyi_tests_release_trybot', 'mac_upload_clang': 'release_bot', 'mac_upload_clang_arm': 'release_bot', @@ -1192,6 +1198,7 @@ 'gpu-fyi-try-win10-nvidia-exp-64': 'gpu_fyi_tests_release_trybot', 'gpu-fyi-try-win10-nvidia-rel-32': 'gpu_fyi_tests_release_trybot_x86', 'gpu-fyi-try-win10-nvidia-rel-64': 'gpu_fyi_tests_release_trybot', + 'win10-clang-tidy-rel': 'release_trybot', 'win10_chromium_inverse_fieldtrials_x64_fyi_rel_ng': 'gpu_tests_release_trybot_resource_allowlisting_invert_fieldtrials', 'win10_chromium_x64_dbg_ng': 'gpu_tests_debug_bot', 'win10_chromium_x64_rel_ng': 'gpu_tests_release_trybot_resource_allowlisting_code_coverage',
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.android.json b/tools/mb/mb_config_expectations/tryserver.chromium.android.json index cc2c207..e2cce38 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.android.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.android.json
@@ -113,6 +113,20 @@ "use_goma": true } }, + "android-clang-tidy-rel": { + "gn_args": { + "blink_enable_generated_code_formatting": false, + "dcheck_always_on": true, + "ffmpeg_branding": "Chrome", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "strip_debug_info": true, + "symbol_level": 0, + "target_os": "android", + "use_goma": true + } + }, "android-cronet-arm-dbg": { "gn_args": { "arm_use_neon": false,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.chromiumos.json b/tools/mb/mb_config_expectations/tryserver.chromium.chromiumos.json index b85a1db2a..09117d8 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.chromiumos.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.chromiumos.json
@@ -178,6 +178,19 @@ "use_goma": true } }, + "linux-chromeos-clang-tidy-rel": { + "gn_args": { + "blink_enable_generated_code_formatting": false, + "dcheck_always_on": true, + "ffmpeg_branding": "ChromeOS", + "is_component_build": false, + "is_debug": false, + "proprietary_codecs": true, + "symbol_level": 0, + "target_os": "chromeos", + "use_goma": true + } + }, "linux-chromeos-compile-dbg": { "gn_args": { "ffmpeg_branding": "ChromeOS", @@ -246,6 +259,19 @@ "use_goma": true } }, + "linux-lacros-clang-tidy-rel": { + "gn_args": { + "also_build_ash_chrome": true, + "blink_enable_generated_code_formatting": false, + "chromeos_is_browser_only": true, + "dcheck_always_on": true, + "is_component_build": false, + "is_debug": false, + "symbol_level": 0, + "target_os": "chromeos", + "use_goma": true + } + }, "linux-lacros-dbg": { "gn_args": { "also_build_ash_chrome": true,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json index 836c00d5..f4dc53c 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.linux.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.linux.json
@@ -75,6 +75,17 @@ "use_goma": true } }, + "fuchsia-clang-tidy-rel": { + "gn_args": { + "blink_enable_generated_code_formatting": false, + "dcheck_always_on": true, + "is_component_build": false, + "is_debug": false, + "symbol_level": 0, + "target_os": "fuchsia", + "use_goma": true + } + }, "fuchsia-compile-x64-dbg": { "gn_args": { "is_component_build": true,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json index e1dd664..30a2770 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.mac.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.mac.json
@@ -227,6 +227,21 @@ "use_lld": false } }, + "ios-clang-tidy-rel": { + "gn_args": { + "dcheck_always_on": false, + "ios_code_signing_identity_description": "Apple Development", + "ios_enable_code_signing": false, + "ios_set_attributes_for_xcode_project_generation": false, + "is_component_build": false, + "is_debug": false, + "symbol_level": 0, + "target_cpu": "arm64", + "target_environment": "device", + "target_os": "ios", + "use_goma": true + } + }, "ios-device": { "gn_args": { "dcheck_always_on": false, @@ -419,6 +434,16 @@ "use_goma": true } }, + "mac-clang-tidy-rel": { + "gn_args": { + "blink_enable_generated_code_formatting": false, + "dcheck_always_on": true, + "is_component_build": false, + "is_debug": false, + "symbol_level": 0, + "use_goma": true + } + }, "mac-inverse-fieldtrials-fyi-rel": { "gn_args": { "blink_enable_generated_code_formatting": false,
diff --git a/tools/mb/mb_config_expectations/tryserver.chromium.win.json b/tools/mb/mb_config_expectations/tryserver.chromium.win.json index d21cc57..7881fb0 100644 --- a/tools/mb/mb_config_expectations/tryserver.chromium.win.json +++ b/tools/mb/mb_config_expectations/tryserver.chromium.win.json
@@ -229,6 +229,16 @@ "use_libfuzzer": true } }, + "win10-clang-tidy-rel": { + "gn_args": { + "blink_enable_generated_code_formatting": false, + "dcheck_always_on": true, + "is_component_build": false, + "is_debug": false, + "symbol_level": 0, + "use_goma": true + } + }, "win10-rel-orchestrator": { "gn_args": { "blink_enable_generated_code_formatting": false,
diff --git a/tools/metrics/actions/actions.xml b/tools/metrics/actions/actions.xml index a37ca80e..b0840a21 100644 --- a/tools/metrics/actions/actions.xml +++ b/tools/metrics/actions/actions.xml
@@ -8031,6 +8031,36 @@ </description> </action> +<action name="Extensions.Toolbar.SiteAccessCombobox.OnAllSitesSelected"> + <owner>emiliapaz@chromium.org</owner> + <owner>extensions-core@chromium.org</owner> + <description> + The user selected run on all sites using the extension's site access + combobox in the Extensions Menu. This is recorded for both keyboard and + mouse activation. + </description> +</action> + +<action name="Extensions.Toolbar.SiteAccessCombobox.OnClickSelected"> + <owner>emiliapaz@chromium.org</owner> + <owner>extensions-core@chromium.org</owner> + <description> + The user selected run on click using the extension's site access combobox in + the Extensions Menu. This is recorded for both keyboard and mouse + activation. + </description> +</action> + +<action name="Extensions.Toolbar.SiteAccessCombobox.OnSiteSelected"> + <owner>emiliapaz@chromium.org</owner> + <owner>extensions-core@chromium.org</owner> + <description> + The user selected run on site using the extension's site access combobox in + the Extensions Menu. This is recorded for both keyboard and mouse + activation. + </description> +</action> + <action name="Extensions.UninstallDialogCancelClick"> <owner>archanasimha@chromium.org</owner> <description>
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml index a88c163..c1d13367a 100644 --- a/tools/metrics/histograms/enums.xml +++ b/tools/metrics/histograms/enums.xml
@@ -3891,6 +3891,14 @@ <int value="3" label="Crashed"/> </enum> +<enum name="ArcContinueBootImpulseStatus"> +<!-- To be kept in sync with ChromeOS enum ArcContinueBootImpulseStatus --> + + <int value="0" label="Arc continue boot impulse succeeded."/> + <int value="1" label="Arc continue boot impulse failed."/> + <int value="2" label="Arc continue boot impulse timed out."/> +</enum> + <enum name="ArcCorePriAbiMigEvent"> <!-- Value from components/arc/mojom/metrics.mojom --> @@ -15327,8 +15335,6 @@ <int value="37" label="HTTP/3 (draft-28)"/> <int value="38" label="HTTP/3 (draft-29)"/> <int value="39" label="HTTP/3 (T051)"/> - <int value="40" label="QUIC (RFC)"/> - <int value="41" label="QUICv2 (draft-01)"/> </enum> <enum name="ConnectionResult"> @@ -20022,6 +20028,12 @@ <int value="2" label="Has enough SCTs"/> </enum> +<enum name="CustomTabsCloseCause"> + <int value="0" label="User action in Chrome (back press, close button)"/> + <int value="1" label="User action in Android (home)"/> + <int value="2" label="Auto-closed"/> +</enum> + <enum name="CustomTabsConnection"> <int value="0" label="Disconnected from service w/o KeepAlive connection"/> <int value="1" label="Disconnected from service with KeepAlive connection"/> @@ -50084,6 +50096,7 @@ <int value="3" label="Cancelled due to omnibox navigation."/> <int value="4" label="Cancelled due to tab crash."/> <int value="5" label="Cancelled due to time out"/> + <int value="6" label="Empty selector"/> </enum> <enum name="LinkToTextShouldOfferResult"> @@ -51061,6 +51074,7 @@ <int value="-2129940395" label="WebAssemblySimd:disabled"/> <int value="-2129013032" label="DocumentTransition:enabled"/> <int value="-2128705444" label="AssistantAppSupport:enabled"/> + <int value="-2128535212" label="GuestOsFiles:enabled"/> <int value="-2127319228" label="enable-media-internals:disabled"/> <int value="-2126697213" label="EnablePalmSuppression:disabled"/> <int value="-2126275491" label="WebViewAppsPackageNamesAllowlist:disabled"/> @@ -52722,6 +52736,7 @@ <int value="-994219683" label="WebBluetoothNewPermissionsBackend:disabled"/> <int value="-994088375" label="VrBrowsingExperimentalRendering:enabled"/> <int value="-994044484" label="TemporaryUnexpireFlagsM76:disabled"/> + <int value="-993583908" label="GuestOsFiles:disabled"/> <int value="-993476089" label="AutoScreenBrightness:disabled"/> <int value="-992785453" label="ExplicitLanguageAsk:disabled"/> <int value="-992554993" label="TemporaryHoldingSpacePreviews:disabled"/>
diff --git a/tools/metrics/histograms/metadata/accessibility/histograms.xml b/tools/metrics/histograms/metadata/accessibility/histograms.xml index ab83add..0a7d813 100644 --- a/tools/metrics/histograms/metadata/accessibility/histograms.xml +++ b/tools/metrics/histograms/metadata/accessibility/histograms.xml
@@ -159,7 +159,7 @@ </histogram> <histogram name="Accessibility.Android.OnDemand.EventsDropped" units="count" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>mschillaci@google.com</owner> <owner>abigailbklein@google.com</owner> <summary> @@ -179,8 +179,28 @@ </summary> </histogram> +<histogram + name="Accessibility.Android.OnDemand.OneHundredPercentEventsDropped.{AXMode}" + units="count" expires_after="2022-06-26"> + <owner>mschillaci@google.com</owner> + <owner>abigailbklein@google.com</owner> + <summary> + Tracks the number of AccessibilityEvents dropped when the OnDemand + accessibility services feature is enabled, and the ComputeAXMode feature is + enabled, and the number of events dropped is 100%. Tracks for when the + AXMode is set to {AXMode}. Recorded a the end of a session. + </summary> + <token key="AXMode"> + <variant name="Basic" + summary="kAXModeBasic - Includes only NativeAPIs and WebContents"/> + <variant name="Complete" + summary="kAXModeComplete - Includes NativeAPIs, WebContents, + InlineTextBoxes, ScreenReader, and HTML"/> + </token> +</histogram> + <histogram name="Accessibility.Android.OnDemand.PercentageDropped" units="%" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>mschillaci@google.com</owner> <owner>abigailbklein@google.com</owner> <summary> @@ -189,6 +209,25 @@ </summary> </histogram> +<histogram name="Accessibility.Android.OnDemand.PercentageDropped.{AXMode}" + units="%" expires_after="2022-06-26"> + <owner>mschillaci@google.com</owner> + <owner>abigailbklein@google.com</owner> + <summary> + Tracks the percentage of AccessibilityEvents dropped when the OnDemand + accessibility services feature is enabled, and the ComputeAXMode feature is + enabled. Tracks for when the AXMode is set to {AXMode}. Recorded at the end + of a session. + </summary> + <token key="AXMode"> + <variant name="Basic" + summary="kAXModeBasic - Includes only NativeAPIs and WebContents"/> + <variant name="Complete" + summary="kAXModeComplete - Includes NativeAPIs, WebContents, + InlineTextBoxes, ScreenReader, and HTML"/> + </token> +</histogram> + <histogram name="Accessibility.Android.ScreenReader{AccessibilityEveryReport}" enum="BooleanEnabled" expires_after="never"> <!-- expires-never: usage drives a11y prioritization in browser and content. --> @@ -1434,7 +1473,7 @@ </histogram> <histogram name="Accessibility.WebSpeech.Duration" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>evliu@google.com</owner> <owner>chrome-media-ux@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/android/histograms.xml b/tools/metrics/histograms/metadata/android/histograms.xml index 92fe699..de91bf76 100644 --- a/tools/metrics/histograms/metadata/android/histograms.xml +++ b/tools/metrics/histograms/metadata/android/histograms.xml
@@ -289,7 +289,7 @@ <histogram name="Android.AutofillAssistant.PaymentRequest.AutofillChanged" enum="AutofillAssistantPaymentRequestAutofillInfoChanged" - expires_after="2022-06-08"> + expires_after="2022-08-07"> <owner>arbesser@google.com</owner> <owner>mcarlen@chromium.org</owner> <summary> @@ -300,7 +300,7 @@ </histogram> <histogram name="Android.AutofillAssistant.PaymentRequest.FirstNameOnly" - enum="Boolean" expires_after="2022-06-08"> + enum="Boolean" expires_after="2022-08-07"> <owner>arbesser@google.com</owner> <owner>mcarlen@chromium.org</owner> <summary> @@ -327,7 +327,7 @@ </histogram> <histogram name="Android.AutofillAssistant.PaymentRequest.Prefilled" - enum="AutofillAssistantPaymentRequestPrefilled" expires_after="2022-06-08"> + enum="AutofillAssistantPaymentRequestPrefilled" expires_after="2022-08-07"> <owner>arbesser@google.com</owner> <owner>mcarlen@chromium.org</owner> <summary> @@ -657,7 +657,7 @@ </histogram> <histogram name="Android.DarkTheme.ThemeSettingsEntry" - enum="AndroidThemeSettingsEntry" expires_after="2022-06-05"> + enum="AndroidThemeSettingsEntry" expires_after="2022-08-07"> <owner>nemco@google.com</owner> <owner>wenyufu@chromium.org</owner> <owner>clank-app-team@google.com</owner> @@ -693,6 +693,9 @@ <histogram name="Android.DexFixer" enum="DexFixerReason" expires_after="2023-01-30"> + <obsolete> + Removed Feb 2020. + </obsolete> <owner>agrieve@chromium.org</owner> <owner>cduvall@chromium.org</owner> <summary> @@ -1936,7 +1939,7 @@ </histogram> <histogram name="Android.Omnibox.InvalidMatch" enum="MatchResult" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>ender@chromium.org</owner> <owner>tedchoc@chromium.org</owner> <owner>mpearson@chromium.org</owner> @@ -2427,7 +2430,7 @@ </histogram> <histogram name="Android.RequestDesktopSite.Changed" enum="SiteLayout" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>shuyng@google.com</owner> <owner>twellington@chromium.org</owner> <summary> @@ -2745,7 +2748,7 @@ </histogram> <histogram name="Android.Survey.DownloadAttemptsBeforeAccepted" units="units" - expires_after="2022-06-01"> + expires_after="2022-08-07"> <owner>skym@chromium.org</owner> <owner>wenyufu@chromium.org</owner> <owner>clank-app-team@google.com</owner> @@ -2802,7 +2805,7 @@ </histogram> <histogram name="Android.Survey.ShowSurvey" enum="BooleanSuccess" - expires_after="2022-06-01"> + expires_after="2022-08-07"> <owner>twellington@chromium.org</owner> <owner>wenyufu@chromium.org</owner> <owner>clank-app-team@google.com</owner> @@ -2812,7 +2815,7 @@ </histogram> <histogram name="Android.Survey.ShowSurveyStatus" - enum="SurveyPresentationStatusCode" expires_after="2022-06-01"> + enum="SurveyPresentationStatusCode" expires_after="2022-08-07"> <owner>aishwaryarj@google.com</owner> <owner>twellington@chromium.org</owner> <owner>wenyufu@chromium.org</owner> @@ -3505,7 +3508,7 @@ </histogram> <histogram name="Android.WebView.NonEmbeddedMetrics.HistogramRecordAge" - units="minutes" expires_after="2022-06-07"> + units="minutes" expires_after="2022-08-07"> <owner>hazems@chromium.org</owner> <owner>ntfschr@chromium.org</owner> <owner>src/android_webview/OWNERS</owner> @@ -3519,7 +3522,7 @@ </histogram> <histogram name="Android.WebView.NonEmbeddedMetrics.NumHistograms" - units="histograms" expires_after="2022-06-07"> + units="histograms" expires_after="2022-08-07"> <owner>ntfschr@chromium.org</owner> <owner>hazems@chromium.org</owner> <owner>src/android_webview/OWNERS</owner> @@ -3532,7 +3535,7 @@ <histogram name="Android.WebView.NonEmbeddedMetrics.ParsingLogResult" enum="AndroidWebViewNonEmbeddedMetricsParsingLogResult" - expires_after="2022-06-07"> + expires_after="2022-08-07"> <owner>hazems@chromium.org</owner> <owner>ntfschr@chromium.org</owner> <owner>src/android_webview/OWNERS</owner> @@ -3558,7 +3561,7 @@ </histogram> <histogram name="Android.WebView.NonEmbeddedMetrics.TransmissionResult" - enum="AndroidWebViewDevUiMetricsTransmission" expires_after="2022-06-07"> + enum="AndroidWebViewDevUiMetricsTransmission" expires_after="2022-08-07"> <owner>ntfschr@chromium.org</owner> <owner>hazems@chromium.org</owner> <owner>src/android_webview/OWNERS</owner> @@ -3698,7 +3701,7 @@ </histogram> <histogram name="Android.WebView.SafeMode.SafeModeEnabled" - enum="BooleanEnabled" expires_after="2022-06-08"> + enum="BooleanEnabled" expires_after="2022-08-07"> <owner>ntfschr@chromium.org</owner> <owner>src/android_webview/OWNERS</owner> <summary> @@ -3742,7 +3745,7 @@ </histogram> <histogram name="Android.WebView.Startup.CreationTime.Stage1.FactoryInit" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>changwan@chromium.org</owner> <owner>src/android_webview/OWNERS</owner> <summary> @@ -3764,7 +3767,7 @@ </histogram> <histogram name="Android.WebView.Startup.CreationTime.Stage2.ProviderInit.Warm" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>changwan@chromium.org</owner> <owner>src/android_webview/OWNERS</owner> <summary> @@ -3828,7 +3831,7 @@ <histogram name="Android.WebView.UniversalAccess.OriginUrlMismatchInHistoryUtil" - enum="BooleanAllowed" expires_after="2022-06-04"> + enum="BooleanAllowed" expires_after="2022-08-07"> <owner>alexmitra@chromium.org</owner> <owner>torne@chromium.org</owner> <owner>src/android_webview/OWNERS</owner>
diff --git a/tools/metrics/histograms/metadata/apps/histograms.xml b/tools/metrics/histograms/metadata/apps/histograms.xml index ab816ef..ea9fa9e 100644 --- a/tools/metrics/histograms/metadata/apps/histograms.xml +++ b/tools/metrics/histograms/metadata/apps/histograms.xml
@@ -620,7 +620,7 @@ </histogram> <histogram name="Apps.AppList.PersistentProto.ReadStatus" - enum="PersistentProtoReadStatus" expires_after="2022-06-05"> + enum="PersistentProtoReadStatus" expires_after="2022-08-07"> <owner>wrong@chromium.org</owner> <owner>tby@chromium.org</owner> <owner>thanhdng@chromium.org</owner> @@ -1654,7 +1654,7 @@ </histogram> <histogram name="Apps.CreateShortcuts.Linux.Result" - enum="WebAppCreateShortcutLinuxResult" expires_after="2022-06-05"> + enum="WebAppCreateShortcutLinuxResult" expires_after="2022-08-07"> <owner>phillis@chromium.org</owner> <owner>cmumford@chromium.org</owner> <summary> @@ -1843,7 +1843,7 @@ </histogram> <histogram - name="Apps.Launcher.ProductivityReorderAnimationSmoothness{TabletOrClamshell}" + name="Apps.Launcher.ProductivityReorderAnimationSmoothness.{TabletOrClamshell}" units="%" expires_after="2022-09-01"> <owner>andrewxu@chromium.org</owner> <owner>chromeos-launcher@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/autofill/histograms.xml b/tools/metrics/histograms/metadata/autofill/histograms.xml index 478f65a6..58e5ebd 100644 --- a/tools/metrics/histograms/metadata/autofill/histograms.xml +++ b/tools/metrics/histograms/metadata/autofill/histograms.xml
@@ -853,7 +853,7 @@ </histogram> <histogram name="Autofill.CreditCardUploadFeedback" - enum="AutofillCreditCardUploadFeedback" expires_after="2022-06-05"> + enum="AutofillCreditCardUploadFeedback" expires_after="2022-08-07"> <owner>siyua@chromium.org</owner> <owner>jsaul@google.com</owner> <summary> @@ -2691,7 +2691,7 @@ </histogram> <histogram name="Autofill.StoredCreditCardCount.Server.WithVirtualCardMetadata" - units="units" expires_after="2022-06-05"> + units="units" expires_after="2022-08-07"> <owner>siyua@chromium.org</owner> <owner>payments-autofill-team@google.com</owner> <summary> @@ -3209,7 +3209,7 @@ </histogram> <histogram name="Autofill.VirtualCard.MetadataSynced" enum="BooleanExists" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>siyua@chromium.org</owner> <owner>payments-autofill-team@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/blink/histograms.xml b/tools/metrics/histograms/metadata/blink/histograms.xml index e0b923c..3aa9f127 100644 --- a/tools/metrics/histograms/metadata/blink/histograms.xml +++ b/tools/metrics/histograms/metadata/blink/histograms.xml
@@ -278,14 +278,14 @@ </histogram> <histogram name="Blink.Canvas.ResourceProviderIsAccelerated" - enum="BooleanHardwareAccelerated" expires_after="2022-06-05"> + enum="BooleanHardwareAccelerated" expires_after="2022-08-07"> <owner>aaronhk@chromium.org</owner> <owner>fserb@chromium.org</owner> <summary>Logs if the canvas resource provider is accelerated or not.</summary> </histogram> <histogram name="Blink.Canvas.ResourceProviderType" - enum="CanvasResourceProviderType" expires_after="2022-06-05"> + enum="CanvasResourceProviderType" expires_after="2022-08-07"> <owner>aaronhk@chromium.org</owner> <owner>fserb@chromium.org</owner> <summary>Records the type of resource provider used for a canvas.</summary> @@ -301,7 +301,7 @@ </histogram> <histogram name="Blink.Canvas.SqrtNumberOfPixels" units="sqrt(pixels)" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>aaronhk@chromium.org</owner> <owner>fserb@chromium.org</owner> <summary> @@ -649,7 +649,7 @@ </histogram> <histogram name="Blink.DarkMode.ApplyToImageOnMainThread" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>pdr@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <summary> @@ -1101,7 +1101,7 @@ </histogram> <histogram base="true" name="Blink.HandleInputEvents.UpdateTime" - units="microseconds" expires_after="2022-06-05"> + units="microseconds" expires_after="2022-08-07"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" --> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" --> @@ -1775,7 +1775,7 @@ </histogram> <histogram name="Blink.OffscreenCanvas.NewOffscreenCanvas" enum="Boolean" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>aaronhk@chromium.org</owner> <owner>fserb@chromium.org</owner> <summary> @@ -1794,7 +1794,7 @@ </histogram> <histogram name="Blink.OffscreenCanvas.TransferControlToOffscreen" - enum="BooleanSuccess" expires_after="2022-06-05"> + enum="BooleanSuccess" expires_after="2022-08-07"> <owner>aaronhk@chromium.org</owner> <owner>fserb@chromium.org</owner> <summary>Records a call to transfer a canvas offscreen.</summary> @@ -2028,7 +2028,7 @@ </histogram> <histogram name="Blink.Sms.Receive.CrossDeviceFailure" - enum="WebOTPCrossDeviceFailure" expires_after="2022-06-05"> + enum="WebOTPCrossDeviceFailure" expires_after="2022-08-07"> <owner>yigu@chromium.org</owner> <owner>web-identity@google.com</owner> <summary> @@ -2159,7 +2159,7 @@ </histogram> <histogram base="true" name="Blink.Style.UpdateTime" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePreFCPSuffixes" --> <!-- Name completed by histogram_suffixes name="BlinkUpdateTimePostFCPSuffixes" --> @@ -2276,7 +2276,7 @@ </histogram> <histogram name="Blink.UseCounter.DocumentPolicy.Header" - enum="DocumentPolicyFeature" expires_after="2022-06-05"> + enum="DocumentPolicyFeature" expires_after="2022-08-07"> <owner>iclelland@chromium.org</owner> <owner>feature-control@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/bookmarks/histograms.xml b/tools/metrics/histograms/metadata/bookmarks/histograms.xml index e5d85c3..8ec75cd 100644 --- a/tools/metrics/histograms/metadata/bookmarks/histograms.xml +++ b/tools/metrics/histograms/metadata/bookmarks/histograms.xml
@@ -141,7 +141,7 @@ </histogram> <histogram name="Bookmarks.Count.OnProfileLoad" units="bookmarks" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>supertri@chromium.org</owner> <owner>isherman@chromium.org</owner> <owner>aidanday@google.com</owner> @@ -215,7 +215,7 @@ </histogram> <histogram name="Bookmarks.EntryPoint" enum="BookmarksEntryPoint" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>ianwen@chromium.org</owner> <component>UI>Browser>Bookmarks</component> <summary>How users add a new bookmark.</summary>
diff --git a/tools/metrics/histograms/metadata/browser/histograms.xml b/tools/metrics/histograms/metadata/browser/histograms.xml index 92f4d2f..d608230 100644 --- a/tools/metrics/histograms/metadata/browser/histograms.xml +++ b/tools/metrics/histograms/metadata/browser/histograms.xml
@@ -111,7 +111,7 @@ </histogram> <histogram name="Browser.PaintPreview.Capture.CompressedOnDiskSize" units="KB" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>ckitagawa@chromium.org</owner> <owner>yashard@chromium.org</owner> <owner>fredmello@chromium.org</owner> @@ -122,7 +122,7 @@ </histogram> <histogram name="Browser.PaintPreview.Capture.NumberOfFramesCaptured" - units="units" expires_after="2022-06-05"> + units="units" expires_after="2022-08-07"> <owner>ckitagawa@chromium.org</owner> <owner>yashard@chromium.org</owner> <owner>fredmello@chromium.org</owner> @@ -132,7 +132,7 @@ </histogram> <histogram name="Browser.PaintPreview.Capture.Success" enum="BooleanSuccess" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>ckitagawa@chromium.org</owner> <owner>yashard@chromium.org</owner> <owner>fredmello@chromium.org</owner> @@ -142,7 +142,7 @@ </histogram> <histogram name="Browser.PaintPreview.Capture.TotalCaptureDuration" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>ckitagawa@chromium.org</owner> <owner>yashard@chromium.org</owner> <owner>fredmello@chromium.org</owner> @@ -204,7 +204,7 @@ </histogram> <histogram name="Browser.PaintPreview.TabbedPlayer.ExitCause" - enum="TabbedPaintPreviewExitCause" expires_after="2022-06-05"> + enum="TabbedPaintPreviewExitCause" expires_after="2022-08-07"> <owner>ckitagawa@chromium.org</owner> <owner>yashard@chromium.org</owner> <owner>fredmello@chromium.org</owner> @@ -474,7 +474,7 @@ </histogram> <histogram name="Browser.Tabs.TabSwitchHasRWHV" enum="BooleanExists" - expires_after="2022-04-26"> + expires_after="2022-08-07"> <owner>joenotcharles@google.com</owner> <owner>catan-team@chromium.org</owner> <summary> @@ -784,7 +784,7 @@ </histogram> <histogram name="BrowserSwitcher.AlternativeBrowser" enum="BrowserType" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>nicolaso@chromium.org</owner> <owner>pastarmovj@chromium.org</owner> <summary> @@ -913,7 +913,7 @@ </histogram> <histogram name="BrowserSwitcher.LaunchTime" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>nicolaso@chromium.org</owner> <owner>pastarmovj@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/chrome/histograms.xml b/tools/metrics/histograms/metadata/chrome/histograms.xml index ecbc0141..3388cde 100644 --- a/tools/metrics/histograms/metadata/chrome/histograms.xml +++ b/tools/metrics/histograms/metadata/chrome/histograms.xml
@@ -160,7 +160,7 @@ </histogram> <histogram name="ChromeColors.ColorOnLoad" enum="ChromeColorsInfo" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>gayane@chromium.org</owner> <owner>yyushkina@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/commerce/histograms.xml b/tools/metrics/histograms/metadata/commerce/histograms.xml index bdfd6220..e2d573ad 100644 --- a/tools/metrics/histograms/metadata/commerce/histograms.xml +++ b/tools/metrics/histograms/metadata/commerce/histograms.xml
@@ -224,6 +224,20 @@ <token key="ManagementType" variants="ManagementTypes"/> </histogram> +<histogram name="Commerce.PriceDrops.{ManagementType}.NotificationReachedCap" + enum="Boolean" expires_after="2022-06-01"> + <owner>zhiyuancai@chromium.org</owner> + <owner>ayman@chromium.org</owner> + <owner>chrome-shopping@google.com</owner> + <summary> + Records whether the number of shown notifications in given window (one day + by default) has reached the cap limit for specified management type. + Recorded when we are trying to show any price drop notifications. + Implemented for Android. + </summary> + <token key="ManagementType" variants="ManagementTypes"/> +</histogram> + <histogram name="Commerce.PriceDrops.{TabUsageStatus}{LocationIdentifier}.ContainsPrice" enum="BooleanContainsPrice" expires_after="2022-06-07">
diff --git a/tools/metrics/histograms/metadata/compositing/histograms.xml b/tools/metrics/histograms/metadata/compositing/histograms.xml index 6a747ea..1a2b737 100644 --- a/tools/metrics/histograms/metadata/compositing/histograms.xml +++ b/tools/metrics/histograms/metadata/compositing/histograms.xml
@@ -532,7 +532,7 @@ </histogram> <histogram name="Compositing.Renderer.LCDTextDisallowedReasonKPixels" - enum="LCDTextDisallowedReason" expires_after="2022-06-05"> + enum="LCDTextDisallowedReason" expires_after="2022-08-07"> <owner>wangxianzhu@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <summary> @@ -709,7 +709,7 @@ </histogram> <histogram name="Compositing.SurfaceAggregator.DeclareResourcesUs" - units="microseconds" expires_after="2022-06-05"> + units="microseconds" expires_after="2022-08-07"> <owner>kylechar@chromium.org</owner> <owner>jonross@chromium.org</owner> <summary> @@ -744,7 +744,7 @@ </histogram> <histogram name="Compositing.SurfaceAggregator.PrewalkUs" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>kylechar@chromium.org</owner> <owner>jonross@chromium.org</owner> <summary> @@ -982,7 +982,7 @@ </summary> </histogram> -<histogram name="Graphics.Smoothness.Jank" units="%" expires_after="2022-07-31"> +<histogram name="Graphics.Smoothness.Jank" units="%" expires_after="2022-08-07"> <owner>sadrul@chromium.org</owner> <owner>mjzhang@chromium.org</owner> <owner>graphics-dev@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/content/histograms.xml b/tools/metrics/histograms/metadata/content/histograms.xml index 700850c3..bc81636 100644 --- a/tools/metrics/histograms/metadata/content/histograms.xml +++ b/tools/metrics/histograms/metadata/content/histograms.xml
@@ -171,7 +171,7 @@ </histogram> <histogram name="ContentSettings.AllowStorageAccessSync" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>cduvall@chromium.org</owner> <owner>jam@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/content_creation/histograms.xml b/tools/metrics/histograms/metadata/content_creation/histograms.xml index f6758fc..0737737f 100644 --- a/tools/metrics/histograms/metadata/content_creation/histograms.xml +++ b/tools/metrics/histograms/metadata/content_creation/histograms.xml
@@ -232,7 +232,7 @@ </histogram> <histogram name="NoteCreation.Funnel" enum="NoteCreationFunnel" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>sebsg@chromium.org</owner> <owner>chrome-creation@google.com</owner> <summary> @@ -298,7 +298,7 @@ </histogram> <histogram name="SharedHighlights.AndroidShareSheet.SharedState" - enum="LinkGenerationSharedStatus" expires_after="2022-06-05"> + enum="LinkGenerationSharedStatus" expires_after="2022-08-07"> <owner>sebsg@chromium.org</owner> <owner>chrome-shared-highlighting@google.com</owner> <summary> @@ -330,7 +330,7 @@ </histogram> <histogram name="SharedHighlights.Desktop.CopiedLinkType" - enum="LinkGenerationCopiedLinkType" expires_after="2022-06-05"> + enum="LinkGenerationCopiedLinkType" expires_after="2022-08-07"> <owner>sebsg@chromium.org</owner> <owner>chrome-shared-highlighting@google.com</owner> <summary> @@ -339,7 +339,7 @@ </histogram> <histogram name="SharedHighlights.LinkGenerated.Error" - enum="LinkGenerationError" expires_after="2022-06-05"> + enum="LinkGenerationError" expires_after="2022-08-07"> <owner>gayane@chromium.org</owner> <owner>chrome-shared-highlighting@google.com</owner> <summary> @@ -432,7 +432,7 @@ </histogram> <histogram name="SharedHighlights.LinkGenerated.TimeToGenerate" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>gayane@chromium.org</owner> <owner>chrome-shared-highlighting@google.com</owner> <summary> @@ -471,7 +471,7 @@ </histogram> <histogram name="SharedHighlights.ObtainReshareLink.Status" - units="LinkToTextReshareStatus" expires_after="2022-06-05"> + units="LinkToTextReshareStatus" expires_after="2022-08-07"> <owner>gayane@chromium.org</owner> <owner>chrome-shared-highlighting@google.com</owner> <summary> @@ -492,7 +492,7 @@ </histogram> <histogram name="TextFragmentAnchor.LinkOpenSource" - enum="TextFragmentLinkOpenSource" expires_after="2022-06-05"> + enum="TextFragmentLinkOpenSource" expires_after="2022-08-07"> <owner>gayane@chromium.org</owner> <owner>chrome-shared-highlighting@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/cookie/histograms.xml b/tools/metrics/histograms/metadata/cookie/histograms.xml index 61a92f7..80960a3 100644 --- a/tools/metrics/histograms/metadata/cookie/histograms.xml +++ b/tools/metrics/histograms/metadata/cookie/histograms.xml
@@ -621,7 +621,7 @@ </histogram> <histogram name="Cookie.SamePartyCookieSameSiteAttributeValue" - enum="CookieSameSiteString" expires_after="2022-06-05"> + enum="CookieSameSiteString" expires_after="2022-08-07"> <owner>cfredric@chromium.org</owner> <owner>kaustubhag@chromium.org</owner> <summary> @@ -632,7 +632,7 @@ </histogram> <histogram name="Cookie.SamePartyReadIncluded.InclusionUnderSameSite" - enum="BooleanIncluded" expires_after="2022-06-05"> + enum="BooleanIncluded" expires_after="2022-08-07"> <owner>cfredric@chromium.org</owner> <owner>bingler@chromium.org</owner> <summary> @@ -653,7 +653,7 @@ </histogram> <histogram name="Cookie.SamePartyReadIncluded.PartyContextSize" - units="registrable domains" expires_after="2022-06-05"> + units="registrable domains" expires_after="2022-08-07"> <owner>cfredric@chromium.org</owner> <owner>bingler@chromium.org</owner> <summary> @@ -690,7 +690,7 @@ </histogram> <histogram name="Cookie.SamePartySetIncluded.PartyContextSize" - units="registrable domains" expires_after="2022-06-05"> + units="registrable domains" expires_after="2022-08-07"> <owner>cfredric@chromium.org</owner> <owner>bingler@chromium.org</owner> <summary> @@ -830,7 +830,7 @@ </histogram> <histogram name="Cookie.TruncatingCharacterInCookieString" - enum="TruncatingCharacterInCookieStringType" expires_after="2022-06-05"> + enum="TruncatingCharacterInCookieStringType" expires_after="2022-08-07"> <owner>bingler@chromium.org</owner> <owner>awillia@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/cras/histograms.xml b/tools/metrics/histograms/metadata/cras/histograms.xml index f5cd17bc..a90c3c3 100644 --- a/tools/metrics/histograms/metadata/cras/histograms.xml +++ b/tools/metrics/histograms/metadata/cras/histograms.xml
@@ -906,7 +906,7 @@ </histogram> <histogram name="Cras.UnderrunsPerDevice" units="count" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>yuhsuan@chromium.org</owner> <owner>chromeos-audio@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/cros_ml/histograms.xml b/tools/metrics/histograms/metadata/cros_ml/histograms.xml index 56c5739..fedf3b3 100644 --- a/tools/metrics/histograms/metadata/cros_ml/histograms.xml +++ b/tools/metrics/histograms/metadata/cros_ml/histograms.xml
@@ -177,7 +177,7 @@ </histogram> <histogram name="MachineLearningService.ProcessError" - enum="MachineLearningServiceProcessError" expires_after="2022-06-05"> + enum="MachineLearningServiceProcessError" expires_after="2022-08-07"> <owner>amoylan@chromium.org</owner> <owner>alanlxl@chromium.org</owner> <owner>honglinyu@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml index 3fd2ad8..1c59030 100644 --- a/tools/metrics/histograms/metadata/custom_tabs/histograms.xml +++ b/tools/metrics/histograms/metadata/custom_tabs/histograms.xml
@@ -35,6 +35,23 @@ </summary> </histogram> +<histogram name="CustomTabs.AutoclosedSessionDuration" units="ms" + expires_after="2022-07-31"> + <owner>jinsukkim@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <owner>cct-team@google.com</owner> + <summary> + Android: Duration in milliseconds of a custom tab session (between onResume + and onPause). This is logged for the sessions closed automatically without + user intervention. Sessions closed by user input (back press/close button) + will not be logged. + + Note that there can be user inputs that go undetected by the logic. So the + histogram can contain false positives i.e. session closed by user but + regarded as auto-closed. + </summary> +</histogram> + <histogram name="CustomTabs.ClientAppId" enum="ClientAppId" expires_after="2022-07-24"> <owner>yusufo@chromium.org</owner> @@ -84,6 +101,18 @@ </summary> </histogram> +<histogram name="CustomTabs.CloseCause" enum="CustomTabsCloseCause" + expires_after="2022-07-31"> + <owner>jinsukkim@chromium.org</owner> + <owner>twellington@chromium.org</owner> + <owner>cct-team@google.com</owner> + <summary> + Android: The reason a custom tab is closed. Main interest is whether a + custom tab is triggered by user inputs like back press/close button click, + or it is automatically closed by the app that opened it. + </summary> +</histogram> + <histogram name="CustomTabs.ConnectionStatusOnReturn.GSA" enum="CustomTabsConnection" expires_after="2022-06-26"> <owner>peconn@chromium.org</owner> @@ -145,7 +174,7 @@ </histogram> <histogram name="CustomTabs.IncognitoCCTCallerId" enum="IncognitoCCTCallerId" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>roagarwal@chromium.org</owner> <owner>chrome-incognito@google.com</owner> <owner>cct-team@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/download/histograms.xml b/tools/metrics/histograms/metadata/download/histograms.xml index 8c14759..14061c9 100644 --- a/tools/metrics/histograms/metadata/download/histograms.xml +++ b/tools/metrics/histograms/metadata/download/histograms.xml
@@ -322,7 +322,7 @@ </histogram> <histogram name="Download.IOSDownloadedFileAction" enum="DownloadedFileAction" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>sdefresne@chromium.org</owner> <owner>ewannpv@chromium.org</owner> <owner>mrefaat@chromium.org</owner> @@ -344,7 +344,7 @@ </histogram> <histogram name="Download.IOSDownloadFileInBackground" - enum="DownloadFileInBackground" expires_after="2022-06-05"> + enum="DownloadFileInBackground" expires_after="2022-08-07"> <owner>sdefresne@chromium.org</owner> <owner>ewannpv@chromium.org</owner> <owner>mrefaat@chromium.org</owner> @@ -357,7 +357,7 @@ </histogram> <histogram name="Download.IOSDownloadFileResult" enum="DownloadFileResult" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>sdefresne@chromium.org</owner> <owner>ewannpv@chromium.org</owner> <owner>mrefaat@chromium.org</owner> @@ -365,7 +365,7 @@ </histogram> <histogram name="Download.IOSDownloadFileUI" enum="DownloadFileUI" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>sdefresne@chromium.org</owner> <owner>ewannpv@chromium.org</owner> <owner>mrefaat@chromium.org</owner> @@ -376,7 +376,7 @@ </histogram> <histogram name="Download.IOSDownloadFileUIGoogleDrive" - enum="DownloadFileUIGoogleDrive" expires_after="2022-06-05"> + enum="DownloadFileUIGoogleDrive" expires_after="2022-08-07"> <owner>sdefresne@chromium.org</owner> <owner>ewannpv@chromium.org</owner> <owner>mrefaat@chromium.org</owner> @@ -388,7 +388,7 @@ </histogram> <histogram name="Download.IOSDownloadMimeType" enum="DownloadMimeTypeResult" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>sdefresne@chromium.org</owner> <owner>ewannpv@chromium.org</owner> <owner>mrefaat@chromium.org</owner> @@ -471,7 +471,7 @@ </histogram> <histogram base="true" name="Download.Later.UI.DialogChoice" - enum="DownloadLaterDialogChoice" expires_after="2022-06-05"> + enum="DownloadLaterDialogChoice" expires_after="2022-08-07"> <!-- Name completed by histogram_suffixes name="DownloadDialogSource" --> <owner>xingliu@chromium.org</owner> @@ -515,7 +515,7 @@ </histogram> <histogram name="Download.MixedContentDialog.Events" - enum="MixedContentDownloadDialogEvent" expires_after="2022-06-05"> + enum="MixedContentDownloadDialogEvent" expires_after="2022-08-07"> <owner>qinmin@chromium.org</owner> <owner>xingliu@chromium.org</owner> <summary> @@ -1162,7 +1162,7 @@ </histogram> <histogram name="Download.Start.PerProfileType" enum="BrowserProfileType" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>sideyilmaz@chromium.org</owner> <owner>chrome-incognito@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/event/histograms.xml b/tools/metrics/histograms/metadata/event/histograms.xml index dad299f..624e7788 100644 --- a/tools/metrics/histograms/metadata/event/histograms.xml +++ b/tools/metrics/histograms/metadata/event/histograms.xml
@@ -71,7 +71,7 @@ </histogram> <histogram name="Event.AsyncTargeting.ResponseTime" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>sadrul@chromium.org</owner> <owner>event-targeting@chromium.org</owner> <summary> @@ -289,7 +289,7 @@ </histogram> <histogram name="Event.Latency.EndToEnd.TouchpadPinch2" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>nzolghadr@chromium.org</owner> <owner>input-dev@chromium.org</owner> <summary> @@ -309,7 +309,7 @@ </histogram> <histogram name="Event.Latency.HitTest" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <summary> @@ -328,7 +328,7 @@ </histogram> <histogram name="Event.Latency.HitTestRecursive" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <summary> @@ -958,7 +958,7 @@ </histogram> <histogram name="Event.Latency.ScrollJank" enum="Boolean" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>ddrone@google.com</owner> <owner>chrometto-team@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/extensions/histograms.xml b/tools/metrics/histograms/metadata/extensions/histograms.xml index 725fc015..26d67e6 100644 --- a/tools/metrics/histograms/metadata/extensions/histograms.xml +++ b/tools/metrics/histograms/metadata/extensions/histograms.xml
@@ -1383,7 +1383,7 @@ </histogram> <histogram name="Extensions.ForceInstalledCreationStage" - enum="ExtensionInstallCreationStage" expires_after="2022-06-05"> + enum="ExtensionInstallCreationStage" expires_after="2022-08-07"> <owner>swapnilgupta@google.com</owner> <owner>burunduk@chromium.org</owner> <owner>managed-devices@google.com</owner> @@ -1441,7 +1441,7 @@ </histogram> <histogram name="Extensions.ForceInstalledFailureManifestInvalidAppStatusError" - enum="ManifestInvalidAppStatusError" expires_after="2022-06-05"> + enum="ManifestInvalidAppStatusError" expires_after="2022-08-07"> <owner>swapnilgupta@google.com</owner> <owner>burunduk@chromium.org</owner> <owner>managed-devices@google.com</owner> @@ -1490,7 +1490,7 @@ </histogram> <histogram name="Extensions.ForceInstalledFailureSandboxUnpackFailureReason2" - enum="ExtensionUnpackFailureReason" expires_after="2022-06-05"> + enum="ExtensionUnpackFailureReason" expires_after="2022-08-07"> <owner>burunduk@chromium.org</owner> <owner>swapnilgupta@google.com</owner> <owner>managed-devices@google.com</owner> @@ -1551,7 +1551,7 @@ <histogram name="Extensions.ForceInstalledFailureWithCrxHeaderInvalidIsCWS" enum="IsForceInstalledExtensionFailedWithCrxHeaderInvalidFromCWSBoolean" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>swapnilgupta@google.com</owner> <owner>burunduk@chromium.org</owner> <owner>managed-devices@google.com</owner> @@ -1565,7 +1565,7 @@ <histogram name="Extensions.ForceInstalledFailureWithCrxHeaderInvalidIsFromCache" - enum="BooleanCacheHit" expires_after="2022-06-05"> + enum="BooleanCacheHit" expires_after="2022-08-07"> <owner>swapnilgupta@google.com</owner> <owner>burunduk@chromium.org</owner> <owner>managed-devices@google.com</owner> @@ -2271,7 +2271,7 @@ </histogram> <histogram name="Extensions.InstallPrompt.Type2" - enum="ExtensionInstallPromptType" expires_after="2022-06-05"> + enum="ExtensionInstallPromptType" expires_after="2022-08-07"> <owner>meacer@chromium.org</owner> <owner>rdevlin.cronin@chromium.org</owner> <summary> @@ -2880,7 +2880,7 @@ </histogram> <histogram name="Extensions.ProcessManagerStartupHostsTime2" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>rdevlin.cronin@chromium.org</owner> <owner>extensions-core@chromium.org</owner> <summary> @@ -3129,6 +3129,17 @@ </summary> </histogram> +<histogram name="Extensions.SyncBlockedByDefaultWebAppMigration" + units="Boolean" expires_after="2022-06-30"> + <owner>alancutter@chromium.org</owner> + <owner>extensions-core@chromium.org</owner> + <summary> + Records true whenever an extension sync install attempt was blocked because + it was a default Chrome app that has been migrated over to a web app. Never + records false. + </summary> +</histogram> + <histogram name="Extensions.SyncGetMessageBundle" units="ms" expires_after="2022-06-30"> <owner>rdevlin.cronin@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/gpu/histograms.xml b/tools/metrics/histograms/metadata/gpu/histograms.xml index b186ec5..deac6a45 100644 --- a/tools/metrics/histograms/metadata/gpu/histograms.xml +++ b/tools/metrics/histograms/metadata/gpu/histograms.xml
@@ -494,7 +494,7 @@ </histogram> <histogram name="GPU.D3D11FeatureLevel" enum="D3D11FeatureLevel" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>sadrul@chromium.org</owner> <owner>zmo@chromium.org</owner> <summary> @@ -504,7 +504,7 @@ </histogram> <histogram name="GPU.D3D12FeatureLevel" enum="D3D12FeatureLevel" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>magchen@chromium.org</owner> <owner>zmo@chromium.org</owner> <summary> @@ -514,7 +514,7 @@ </histogram> <histogram name="GPU.D3D12HighestShaderModel" enum="D3DShaderModel" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>magchen@chromium.org</owner> <owner>zmo@chromium.org</owner> <summary> @@ -771,7 +771,7 @@ </histogram> <histogram name="GPU.EnsureWorkVisibleDuration" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>alemate@chromium.org</owner> <owner>magchen@chromium.org</owner> <owner>oshima@chromium.org</owner> @@ -787,7 +787,7 @@ </histogram> <histogram name="GPU.EnsureWorkVisibleDurationLowRes" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>alemate@chromium.org</owner> <owner>magchen@chromium.org</owner> <owner>oshima@chromium.org</owner> @@ -874,7 +874,7 @@ </summary> </histogram> -<histogram name="GPU.GpuCount" units="gpus" expires_after="2022-06-05"> +<histogram name="GPU.GpuCount" units="gpus" expires_after="2022-08-07"> <owner>zmo@chromium.org</owner> <owner>graphics-dev@chromium.org</owner> <summary> @@ -1111,7 +1111,7 @@ </histogram> <histogram name="GPU.MultiGpu.AMD" enum="AMDDeviceId" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>zmo@chromium.org</owner> <owner>graphics-dev@chromium.org</owner> <summary> @@ -1121,7 +1121,7 @@ </histogram> <histogram name="GPU.MultiGpu.Nvidia" enum="NvidiaDeviceId" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>zmo@chromium.org</owner> <owner>graphics-dev@chromium.org</owner> <summary> @@ -1339,7 +1339,7 @@ </histogram> <histogram name="GPU.Scheduler.TaskDependencyTime" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>berlu@chromium.org</owner> <owner>chrome-gpu-metrics@google.com</owner> <summary> @@ -1351,7 +1351,7 @@ </histogram> <histogram name="GPU.Scheduler.TaskSchedulingDelayTime" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>berlu@chromium.org</owner> <owner>chrome-gpu-metrics@google.com</owner> <summary> @@ -1365,7 +1365,7 @@ </histogram> <histogram name="GPU.Scheduler.ThreadSuspendedTime" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>berlu@chromium.org</owner> <owner>chrome-gpu-metrics@google.com</owner> <summary> @@ -1456,7 +1456,7 @@ </histogram> <histogram name="GPU.SwapTimeUs" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>vasilyt@chromium.org</owner> <owner>backer@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/history/histograms.xml b/tools/metrics/histograms/metadata/history/histograms.xml index 677536f..881c717 100644 --- a/tools/metrics/histograms/metadata/history/histograms.xml +++ b/tools/metrics/histograms/metadata/history/histograms.xml
@@ -1103,7 +1103,7 @@ </histogram> <histogram name="History.MonthlyURLCount" units="urls" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>mpearson@chromium.org</owner> <owner>sky@chromium.org</owner> <summary> @@ -1236,7 +1236,7 @@ </histogram> <histogram name="History.VisitTableCount" units="visits" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>mpearson@chromium.org</owner> <owner>sky@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/ios/histograms.xml b/tools/metrics/histograms/metadata/ios/histograms.xml index f2011e85..560a33d 100644 --- a/tools/metrics/histograms/metadata/ios/histograms.xml +++ b/tools/metrics/histograms/metadata/ios/histograms.xml
@@ -349,7 +349,7 @@ </histogram> <histogram name="IOS.DefaultBrowserFullscreenTailoredPromoAllTabs" - enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2022-06-05"> + enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2022-08-07"> <owner>rkgibson@chromium.org</owner> <owner>djean@chromium.org</owner> <summary> @@ -359,7 +359,7 @@ </histogram> <histogram name="IOS.DefaultBrowserFullscreenTailoredPromoMadeForIOS" - enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2022-06-05"> + enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2022-08-07"> <owner>rkgibson@chromium.org</owner> <owner>djean@chromium.org</owner> <summary> @@ -369,7 +369,7 @@ </histogram> <histogram name="IOS.DefaultBrowserFullscreenTailoredPromoStaySafe" - enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2022-06-05"> + enum="IOSDefaultBrowserFullscreenPromoAction" expires_after="2022-08-07"> <owner>rkgibson@chromium.org</owner> <owner>djean@chromium.org</owner> <summary> @@ -944,7 +944,7 @@ </histogram> <histogram name="IOS.NTP.Impression" enum="IOSNTPImpression" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>gambard@chromium.org</owner> <summary> The type of NTP impressions on iOS, split by type of suggestions shown @@ -1378,7 +1378,7 @@ </histogram> <histogram name="IOS.TabGrid.Selection.ShareTabs" units="Tabs" - expires_after="2022-05-08"> + expires_after="2022-08-07"> <owner>mrefaat@chromium.org</owner> <owner>michaeldo@chromium.org</owner> <owner>bling-team@google.com</owner> @@ -1444,7 +1444,7 @@ </histogram> <histogram name="IOS.WidgetKit.Action" enum="IOSWidgetKitAction" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>rkgibson@google.com</owner> <owner>muradyan@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/language/histograms.xml b/tools/metrics/histograms/metadata/language/histograms.xml index e7a4be2..1258373 100644 --- a/tools/metrics/histograms/metadata/language/histograms.xml +++ b/tools/metrics/histograms/metadata/language/histograms.xml
@@ -282,7 +282,7 @@ <histogram name="LanguageUsage.UI.Android.IsLocaleUpdated" enum="LanguageUsage.UI.Android.LocaleUpdateStatus" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>perrier@chromium.org</owner> <owner>chrome-language@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/login/histograms.xml b/tools/metrics/histograms/metadata/login/histograms.xml index ab3f8e1..d25bbf7 100644 --- a/tools/metrics/histograms/metadata/login/histograms.xml +++ b/tools/metrics/histograms/metadata/login/histograms.xml
@@ -32,13 +32,37 @@ </summary> </histogram> +<histogram name="Login.ArcContinueBootImpulseStatus" + enum="ArcContinueBootImpulseStatus" expires_after="2022-06-30"> + <owner>vsomani@google.com</owner> + <owner>arc-core@google.com</owner> + <summary> + Records the status of Arc continue boot impulse. This is emitted every time + we upgrade from a mini to full container. + </summary> +</histogram> + <histogram name="Login.ArcContinueBootImpulseTime" units="ms" expires_after="2022-03-30"> + <obsolete> + Removed 2022/02, replaced with ArcContinueBootImpulseTime2. + </obsolete> <owner>mhasank@google.com</owner> <owner>arc-core@google.com</owner> <summary> Tracks the time to execute arc-boot-continue impulse. This is emitted when - we upgrade the ARC container from mini to full. + we successfully upgrade the ARC container from mini to full. + </summary> +</histogram> + +<histogram name="Login.ArcContinueBootImpulseTime2" units="ms" + expires_after="2022-06-30"> + <owner>mhasank@google.com</owner> + <owner>arc-core@google.com</owner> + <summary> + Tracks the time to execute arc-boot-continue impulse. This is emitted when + we successfully upgrade the ARC container from mini to full. This metrics + increases the number of buckets to 50 and a maximum duration of 60 seconds. </summary> </histogram>
diff --git a/tools/metrics/histograms/metadata/media/histograms.xml b/tools/metrics/histograms/metadata/media/histograms.xml index 1b8122a..625253f 100644 --- a/tools/metrics/histograms/metadata/media/histograms.xml +++ b/tools/metrics/histograms/metadata/media/histograms.xml
@@ -496,7 +496,7 @@ </histogram> <histogram name="Media.Audio.CoreAudioDispatchOverrideLookupEvent" - enum="CoreAudioDispatchOverrideLookupEvent" expires_after="2022-06-05"> + enum="CoreAudioDispatchOverrideLookupEvent" expires_after="2022-08-07"> <owner>guidou@chromium.org</owner> <owner>olka@chromium.org</owner> <summary> @@ -735,7 +735,7 @@ </histogram> <histogram name="Media.Audio.Processing.CaptureDelayMs" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>guidou@chromium.org</owner> <owner>olka@chromium.org</owner> <summary> @@ -746,7 +746,7 @@ </histogram> <histogram name="Media.Audio.Processing.CaptureDelayVarianceMs" - units="ms squared" expires_after="2022-06-05"> + units="ms squared" expires_after="2022-08-07"> <owner>guidou@chromium.org</owner> <owner>olka@chromium.org</owner> <summary> @@ -757,7 +757,7 @@ </histogram> <histogram name="Media.Audio.Processing.RenderDelayMs" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>guidou@chromium.org</owner> <owner>olka@chromium.org</owner> <summary> @@ -768,7 +768,7 @@ </histogram> <histogram name="Media.Audio.Processing.RenderDelayVarianceMs" - units="ms squared" expires_after="2022-06-05"> + units="ms squared" expires_after="2022-08-07"> <owner>guidou@chromium.org</owner> <owner>olka@chromium.org</owner> <summary> @@ -789,7 +789,7 @@ </histogram> <histogram name="Media.Audio.Processing.TotalDelayVarianceMs" - units="ms squared" expires_after="2022-06-05"> + units="ms squared" expires_after="2022-08-07"> <owner>guidou@chromium.org</owner> <owner>olka@chromium.org</owner> <summary> @@ -911,7 +911,7 @@ </histogram> <histogram name="Media.Audio.Render.OutputDeviceAuthorizationTimedOut" - enum="BooleanTimedOut" expires_after="2022-06-05"> + enum="BooleanTimedOut" expires_after="2022-08-07"> <owner>guidou@chromium.org</owner> <owner>olka@chromium.org</owner> <summary> @@ -1236,7 +1236,7 @@ </histogram> <histogram name="Media.AudioOutputController.ProxyStreamCreationResult" - enum="AudioOutputStreamCreationResult" expires_after="2022-06-05"> + enum="AudioOutputStreamCreationResult" expires_after="2022-08-07"> <owner>guidou@chromium.org</owner> <owner>olka@chromium.org</owner> <summary> @@ -1250,7 +1250,7 @@ <histogram name="Media.AudioOutputController.ProxyStreamCreationResultForDeviceChange" - enum="AudioOutputStreamCreationResult" expires_after="2022-06-05"> + enum="AudioOutputStreamCreationResult" expires_after="2022-08-07"> <owner>guidou@chromium.org</owner> <owner>olka@chromium.org</owner> <summary> @@ -1996,7 +1996,7 @@ </histogram> <histogram name="Media.EME.EncryptedMediaEnabled" enum="BooleanEnabled" - expires_after="2022-05-07"> + expires_after="2022-08-07"> <owner>xhwang@chromium.org</owner> <owner>media-dev@chromium.org</owner> <summary> @@ -2049,7 +2049,7 @@ </histogram> <histogram name="Media.EME.MediaDrm.GetOriginIdResult" enum="GetOriginIdResult" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jrummell@chromium.org</owner> <owner>media-dev@chromium.org</owner> <summary> @@ -2125,7 +2125,7 @@ <histogram name="Media.EME.MediaFoundationService.Widevine.HardwareSecure.IsTypeSupported" - units="ms" expires_after="2022-05-07"> + units="ms" expires_after="2022-08-07"> <owner>xhwang@chromium.org</owner> <owner>media-dev@chromium.org</owner> <summary> @@ -2182,7 +2182,7 @@ </histogram> <histogram name="Media.EME.UrlProvisionFetcher.ResponseCode" - enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-06-05"> + enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-08-07"> <owner>jrummell@chromium.org</owner> <owner>media-dev@chromium.org</owner> <summary> @@ -2418,7 +2418,7 @@ </histogram> <histogram name="Media.GlobalMediaControls.EntryPoint" - enum="GlobalMediaControlsEntryPoint" expires_after="2022-06-05"> + enum="GlobalMediaControlsEntryPoint" expires_after="2022-08-07"> <owner>takumif@chromium.org</owner> <owner>openscreen-eng@google.com</owner> <owner>media-dev@chromium.org</owner> @@ -3830,7 +3830,7 @@ </histogram> <histogram name="Media.RTCVideoDecoderError" enum="MediaStatusCode" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>posciak@chromium.org</owner> <owner>liberato@chromium.org</owner> <owner>webrtc-video@google.com</owner> @@ -3988,7 +3988,7 @@ </histogram> <histogram name="Media.Session.Play" enum="MediaSessionActionSource" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>steimel@chromium.org</owner> <owner>media-dev@chromium.org</owner> <summary> @@ -5296,7 +5296,7 @@ </histogram> <histogram name="MediaRouter.Cast.LaunchSessionResponse.AppType" - enum="MediaRouterResponseReceiverAppType" expires_after="2022-06-08"> + enum="MediaRouterResponseReceiverAppType" expires_after="2022-08-07"> <owner>muyaoxu@google.com</owner> <owner>openscreen-eng@google.com</owner> <summary> @@ -5420,7 +5420,7 @@ </histogram> <histogram name="MediaRouter.Dial.CreateRoute" - enum="MediaRouterDialCreateRouteResult" expires_after="2022-06-05"> + enum="MediaRouterDialCreateRouteResult" expires_after="2022-08-07"> <owner>takumif@chromium.org</owner> <owner>mfoltz@chromium.org</owner> <owner>openscreen-eng@google.com</owner> @@ -5431,7 +5431,7 @@ </histogram> <histogram name="MediaRouter.Dial.FetchAppInfo" - enum="MediaRouterDialFetchAppInfoResult" expires_after="2022-06-05"> + enum="MediaRouterDialFetchAppInfoResult" expires_after="2022-08-07"> <owner>takumif@chromium.org</owner> <owner>mfoltz@chromium.org</owner> <owner>openscreen-eng@google.com</owner> @@ -5453,7 +5453,7 @@ </histogram> <histogram name="MediaRouter.Dial.ParseMessage" - enum="MediaRouterDialParseMessageResult" expires_after="2022-06-05"> + enum="MediaRouterDialParseMessageResult" expires_after="2022-08-07"> <owner>takumif@chromium.org</owner> <owner>mfoltz@chromium.org</owner> <owner>openscreen-eng@google.com</owner> @@ -5465,7 +5465,7 @@ </histogram> <histogram name="MediaRouter.Dial.ParsingError" - enum="MediaRouterDialParsingError" expires_after="2022-06-05"> + enum="MediaRouterDialParsingError" expires_after="2022-08-07"> <owner>takumif@chromium.org</owner> <owner>mfoltz@chromium.org</owner> <owner>openscreen-eng@google.com</owner> @@ -5526,7 +5526,7 @@ </histogram> <histogram name="MediaRouter.Provider.CreateRoute.Result" - enum="MediaRouteProviderResult" expires_after="2022-06-05"> + enum="MediaRouteProviderResult" expires_after="2022-08-07"> <!-- Name completed by histogram_suffixes name="MediaRouteProvider" --> <owner>takumif@chromium.org</owner> @@ -5554,7 +5554,7 @@ </histogram> <histogram name="MediaRouter.Provider.TerminateRoute.Result" - enum="MediaRouteProviderResult" expires_after="2022-06-05"> + enum="MediaRouteProviderResult" expires_after="2022-08-07"> <!-- Name completed by histogram_suffixes name="MediaRouteProvider" --> <owner>takumif@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/memory/histograms.xml b/tools/metrics/histograms/metadata/memory/histograms.xml index c7a4362..2b60094a 100644 --- a/tools/metrics/histograms/metadata/memory/histograms.xml +++ b/tools/metrics/histograms/metadata/memory/histograms.xml
@@ -1088,7 +1088,7 @@ </histogram> <histogram name="Memory.Experimental.Renderer.HighestPrivateMemoryFootprint" - units="MB" expires_after="2022-06-05"> + units="MB" expires_after="2022-08-07"> <owner>tasak@google.com</owner> <owner>bartekn@google.com</owner> <summary> @@ -1538,7 +1538,7 @@ </histogram> <histogram name="Memory.NativeLibrary.MappedAndResidentMemoryFootprint3" - units="KB" expires_after="2022-06-05"> + units="KB" expires_after="2022-08-07"> <owner>lizeb@chromium.org</owner> <owner>pasko@chromium.org</owner> <summary> @@ -1601,7 +1601,7 @@ </histogram> <histogram name="Memory.NetworkService.PrivateMemoryFootprint" units="MiB" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>mmenke@chromium.org</owner> <owner>morlovich@chromium.org</owner> <owner>erikchen@chromium.org</owner> @@ -2118,7 +2118,7 @@ </histogram> <histogram name="Memory.ParkableString.DiskWriteTime.5min" units="ms" - expires_after="2022-04-17"> + expires_after="2022-08-07"> <owner>lizeb@chromium.org</owner> <owner>pasko@chromium.org</owner> <summary> @@ -2465,7 +2465,7 @@ </histogram> <histogram name="Memory.RendererProcessCount" units="processes" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>creis@chromium.org</owner> <owner>nasko@chromium.org</owner> <summary> @@ -2631,7 +2631,7 @@ </histogram> <histogram name="Memory.Total.RendererPrivateMemoryFootprint" units="MB" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>tommckee@chromium.org</owner> <summary> A rough estimate of the private memory footprint of all renderer processes.
diff --git a/tools/metrics/histograms/metadata/mobile/histograms.xml b/tools/metrics/histograms/metadata/mobile/histograms.xml index 2cb12d3..7439dd07 100644 --- a/tools/metrics/histograms/metadata/mobile/histograms.xml +++ b/tools/metrics/histograms/metadata/mobile/histograms.xml
@@ -318,7 +318,7 @@ </histogram> <histogram name="Mobile.Messages.Translate.Modal.Event" - enum="MobileMessagesTranslateModalEvent" expires_after="2022-06-05"> + enum="MobileMessagesTranslateModalEvent" expires_after="2022-08-07"> <owner>sczs@chromium.org</owner> <owner>thegreenfrog@chromium.org</owner> <summary> @@ -957,7 +957,7 @@ </histogram> <histogram name="MobileOmnibox.PressedClipboardSuggestionAge" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jdonnelly@chromium.org</owner> <owner>mpearson@chromium.org</owner> <summary> @@ -973,7 +973,7 @@ </histogram> <histogram name="MobileSignInPromo.BookmarkManager.ImpressionsTilDismiss" - units="impressions" expires_after="2022-06-05"> + units="impressions" expires_after="2022-08-07"> <owner>jlebel@chromium.org</owner> <owner>chrome-signin-team@google.com</owner> <summary> @@ -1005,7 +1005,7 @@ </histogram> <histogram name="MobileSignInPromo.NTPContentSuggestions.ImpressionsTilXButton" - units="impressions" expires_after="2022-06-05"> + units="impressions" expires_after="2022-08-07"> <owner>bsazonov@chromium.org</owner> <owner>chrome-signin-team@google.com</owner> <summary> @@ -1106,7 +1106,7 @@ </histogram> <histogram name="MobileStartup.LaunchType" enum="LaunchType" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>tedchoc@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/navigation/histograms.xml b/tools/metrics/histograms/metadata/navigation/histograms.xml index 1c10b10..0ef7eb8 100644 --- a/tools/metrics/histograms/metadata/navigation/histograms.xml +++ b/tools/metrics/histograms/metadata/navigation/histograms.xml
@@ -248,7 +248,7 @@ </histogram> <histogram name="BackForwardCache.HistoryNavigationOutcome.BlocklistedFeature" - enum="WebSchedulerTrackedFeature" expires_after="2022-06-05"> + enum="WebSchedulerTrackedFeature" expires_after="2022-08-07"> <owner>hajimehoshi@chromium.org</owner> <owner>bfcache-dev@chromium.org</owner> <summary> @@ -283,7 +283,7 @@ <histogram name="BackForwardCache.HistoryNavigationOutcome.DisabledForRenderFrameHostReason2" enum="BackForwardCacheDisabledForRenderFrameHostReason2" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>carlscab@chromium.org</owner> <owner>hajimehoshi@chromium.org</owner> <owner>bfcache-dev@chromium.org</owner> @@ -1029,7 +1029,7 @@ </histogram> <histogram name="Navigation.RequiresDedicatedProcess" - enum="NavigationRequiresDedicatedProcess" expires_after="2022-06-05"> + enum="NavigationRequiresDedicatedProcess" expires_after="2022-08-07"> <owner>alexmos@chromium.org</owner> <owner>lukasza@chromium.org</owner> <summary> @@ -1386,7 +1386,7 @@ </histogram> <histogram name="Prerender.FinalStatus" enum="PrerenderFinalStatus" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>ryansturm@chromium.org</owner> <owner>tbansal@chromium.org</owner> <summary> @@ -1474,7 +1474,7 @@ </histogram> <histogram name="Prerender.PrerenderLoadComplete" units="BooleanSuccess" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>gambard@chromium.org</owner> <owner>justincohen@chromium.org</owner> <summary> @@ -1511,7 +1511,7 @@ </histogram> <histogram name="Prerender.PrerenderTimeSaved" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>gambard@chromium.org</owner> <owner>justincohen@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/nearby/histograms.xml b/tools/metrics/histograms/metadata/nearby/histograms.xml index 3d1a85d..5c45e2d 100644 --- a/tools/metrics/histograms/metadata/nearby/histograms.xml +++ b/tools/metrics/histograms/metadata/nearby/histograms.xml
@@ -100,17 +100,6 @@ <summary>Records whether BLE scanning has been stopped successfully.</summary> </histogram> -<histogram name="Nearby.Connections.Bluetooth.Socket.{Operation}.Result" - enum="BooleanSuccess" expires_after="2023-02-01"> - <owner>hansenmichael@google.com</owner> - <owner>nearby-share-chromeos-eng@google.com</owner> - <summary>Records whether {Operation} has succeeded.</summary> - <token key="Operation"> - <variant name="Read" summary="reading from the input stream"/> - <variant name="Write" summary="writing to the output stream"/> - </token> -</histogram> - <histogram name="Nearby.Connections.InstantMessaging.ReceiveExpress.NumParsingAttempts" units="attempts" expires_after="2023-02-01"> @@ -242,6 +231,24 @@ </summary> </histogram> +<histogram name="Nearby.Connections.{Medium}.Socket.{Operation}.Result" + enum="BooleanSuccess" expires_after="2023-02-01"> + <owner>hansenmichael@google.com</owner> + <owner>nearby-share-chromeos-eng@google.com</owner> + <summary> + Records success or failure when {Operation} of a {Medium} socket. Emitted + during cross-device data transfers. + </summary> + <token key="Medium"> + <variant name="Bluetooth" summary="Bluetooth"/> + <variant name="WifiLan" summary="WifiLan TCP"/> + </token> + <token key="Operation"> + <variant name="Read" summary="reading from the input stream"/> + <variant name="Write" summary="writing to the output stream"/> + </token> +</histogram> + <histogram name="Nearby.Share.BackgroundScanning.DeviceNearbySharing.Notification.Flow" enum="NearbyShareBackgroundScanningDeviceNearbySharingNotificationFlowEvent" @@ -880,6 +887,7 @@ <variant name=".UnknownMediumUpgrade" summary="an unknown bandwidth-upgraded medium"/> <variant name=".WebRtcUpgrade" summary="an upgraded WebRTC medium"/> + <variant name=".WifiLanUpgrade" summary="an upgraded WifiLan medium"/> </token> </histogram> @@ -957,6 +965,8 @@ summary="when using an unknown bandwidth-upgraded medium"/> <variant name=".WebRtcUpgrade" summary="when using an upgraded WebRTC medium"/> + <variant name=".WifiLanUpgrade" + summary="when using an upgraded WifiLan medium"/> </token> </histogram> @@ -988,6 +998,8 @@ summary="when using an unknown bandwidth-upgraded medium"/> <variant name=".WebRtcUpgrade" summary="when using an upgraded WebRTC medium"/> + <variant name=".WifiLanUpgrade" + summary="when using an upgraded WifiLan medium"/> </token> </histogram>
diff --git a/tools/metrics/histograms/metadata/net/histograms.xml b/tools/metrics/histograms/metadata/net/histograms.xml index 4499730..d2562b8 100644 --- a/tools/metrics/histograms/metadata/net/histograms.xml +++ b/tools/metrics/histograms/metadata/net/histograms.xml
@@ -1511,7 +1511,7 @@ </histogram> <histogram name="Net.HasBrokenNEON" enum="BooleanBroken" - expires_after="2022-05-01"> + expires_after="2022-08-07"> <owner>davidben@chromium.org</owner> <summary> Records, on startup, for ARM devices running Android, whether the CPU is
diff --git a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml index b8a208e..b0f3ad08 100644 --- a/tools/metrics/histograms/metadata/new_tab_page/histograms.xml +++ b/tools/metrics/histograms/metadata/new_tab_page/histograms.xml
@@ -23,7 +23,7 @@ <histograms> <histogram name="NewTabPage.ActionAndroid2" enum="NewTabPageActionAndroid2" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>twellington@chromium.org</owner> <owner>finkm@chromium.org</owner> <summary> @@ -228,7 +228,7 @@ </histogram> <histogram name="NewTabPage.ContentSuggestions.ArticlesListVisible" - enum="BooleanVisible" expires_after="2022-06-05"> + enum="BooleanVisible" expires_after="2022-08-07"> <owner>freedjm@chromium.org</owner> <owner>feed@chromium.org</owner> <summary> @@ -516,7 +516,7 @@ </histogram> <histogram name="NewTabPage.ContentSuggestions.Preferences.RemoteSuggestions" - enum="BooleanEnabled" expires_after="2022-06-05"> + enum="BooleanEnabled" expires_after="2022-08-07"> <owner>carlosk@chromium.org</owner> <owner>freedjm@chromium.org</owner> <owner>feed@chromium.org</owner> @@ -746,7 +746,7 @@ </histogram> <histogram name="NewTabPage.Customized" enum="NTPCustomizedFeatures" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>tiborg@chromium.org</owner> <owner>yyushkina@chromium.org</owner> <owner>chrome-desktop-ntp@google.com</owner> @@ -757,7 +757,7 @@ </histogram> <histogram name="NewTabPage.CustomizedShortcuts" - enum="NTPCustomizedShortcutSettings" expires_after="2022-06-05"> + enum="NTPCustomizedShortcutSettings" expires_after="2022-08-07"> <owner>tiborg@chromium.org</owner> <owner>yyushkina@chromium.org</owner> <owner>chrome-desktop-ntp@google.com</owner> @@ -782,7 +782,7 @@ </histogram> <histogram name="NewTabPage.CustomizeShortcutAction" - enum="NTPCustomizeShortcutAction" expires_after="2022-06-05"> + enum="NTPCustomizeShortcutAction" expires_after="2022-08-07"> <owner>tiborg@chromium.org</owner> <owner>yyushkina@chromium.org</owner> <owner>chrome-desktop-ntp@google.com</owner> @@ -1174,7 +1174,7 @@ </histogram> <histogram name="NewTabPage.MostVisitedMigratedDefaultAppType" - enum="TypeOfDeletedMostVisitedApp" expires_after="M103"> + enum="TypeOfDeletedMostVisitedApp" expires_after="2022-08-07"> <owner>dibyapal@chromium.org</owner> <owner>desktop-pwas-team@google.com</owner> <summary> @@ -1666,7 +1666,7 @@ </summary> </histogram> -<histogram name="NewTabPage.TimeSpent" units="ms" expires_after="2022-06-05"> +<histogram name="NewTabPage.TimeSpent" units="ms" expires_after="2022-08-07"> <owner>freedjm@chromium.org</owner> <owner>feed@chromium.org</owner> <owner>olivierrobin@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/notifications/histograms.xml b/tools/metrics/histograms/metadata/notifications/histograms.xml index a8d3d48..1121a38 100644 --- a/tools/metrics/histograms/metadata/notifications/histograms.xml +++ b/tools/metrics/histograms/metadata/notifications/histograms.xml
@@ -39,7 +39,7 @@ </histogram> <histogram name="Notifications.Android.Build" enum="BooleanSuccess" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>peter@chromium.org</owner> <owner>knollr@chromium.org</owner> <summary> @@ -286,7 +286,7 @@ </histogram> <histogram name="Notifications.Database.ExpiredNotificationCount" - units="notifications" expires_after="2022-06-05"> + units="notifications" expires_after="2022-08-07"> <owner>knollr@chromium.org</owner> <owner>peter@chromium.org</owner> <summary> @@ -460,7 +460,7 @@ </histogram> <histogram name="Notifications.macOS.ServiceProcessKilled" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>knollr@chromium.org</owner> <owner>peter@chromium.org</owner> <summary> @@ -611,7 +611,7 @@ </histogram> <histogram name="Notifications.PersistentNotificationDisplayResult" - enum="PersistentNotificationDisplayResult" expires_after="2022-06-05"> + enum="PersistentNotificationDisplayResult" expires_after="2022-08-07"> <owner>knollr@chromium.org</owner> <owner>peter@chromium.org</owner> <summary> @@ -631,7 +631,7 @@ </histogram> <histogram name="Notifications.PersistentWebNotificationClickResult" - enum="PlatformNotificationStatus" expires_after="2022-06-05"> + enum="PlatformNotificationStatus" expires_after="2022-08-07"> <owner>peter@chromium.org</owner> <owner>deepak.m1@samsung.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/omnibox/histograms.xml b/tools/metrics/histograms/metadata/omnibox/histograms.xml index 913dedb..c997173 100644 --- a/tools/metrics/histograms/metadata/omnibox/histograms.xml +++ b/tools/metrics/histograms/metadata/omnibox/histograms.xml
@@ -47,7 +47,7 @@ </histogram> <histogram name="Omnibox.AnswerParseType" enum="SuggestionAnswerType" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jdonnelly@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> <summary> @@ -271,7 +271,7 @@ </histogram> <histogram name="Omnibox.EnteredKeywordMode2" enum="OmniboxEnteredKeywordMode2" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jdonnelly@chromium.org</owner> <owner>mpearson@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> @@ -567,7 +567,7 @@ </histogram> <histogram name="Omnibox.NumTypedTerms" units="terms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jdonnelly@chromium.org</owner> <owner>mpearson@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> @@ -624,7 +624,7 @@ </histogram> <histogram name="Omnibox.PedalShown" enum="SuggestionPedalType" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jdonnelly@chromium.org</owner> <owner>orinj@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> @@ -693,7 +693,7 @@ </histogram> <histogram name="Omnibox.SearchEngineType" enum="OmniboxSearchEngineType" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jdonnelly@chromium.org</owner> <owner>mpearson@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> @@ -703,7 +703,7 @@ </histogram> <histogram name="Omnibox.SearchPrefetch.PrefetchEligibilityReason" - enum="SearchPrefetchEligibilityReason" expires_after="2022-06-05"> + enum="SearchPrefetchEligibilityReason" expires_after="2022-08-07"> <owner>ryansturm@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> <summary> @@ -715,7 +715,7 @@ </histogram> <histogram name="Omnibox.SearchPrefetch.PrefetchFinalStatus" - enum="SearchPrefetchFinalStatus" expires_after="2022-06-05"> + enum="SearchPrefetchFinalStatus" expires_after="2022-08-07"> <owner>ryansturm@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> <summary> @@ -725,7 +725,7 @@ </histogram> <histogram name="Omnibox.SearchPrefetch.PrefetchServingReason" - enum="SearchPrefetchServingReason" expires_after="2022-06-05"> + enum="SearchPrefetchServingReason" expires_after="2022-08-07"> <owner>ryansturm@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> <summary> @@ -747,7 +747,7 @@ </histogram> <histogram name="Omnibox.SelectedPosition" units="position" - expires_after="2022-07-31"> + expires_after="2022-08-07"> <owner>jdonnelly@chromium.org</owner> <owner>mpearson@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> @@ -797,7 +797,7 @@ </histogram> <histogram name="Omnibox.SuggestionUsed.OfferedTabMatch" enum="BooleanOffered" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>gangwu@chromium.org</owner> <owner>mpearson@chromium.org</owner> <owner>jdonnelly@chromium.org</owner> @@ -820,7 +820,7 @@ </histogram> <histogram name="Omnibox.SuggestionUsed.Pedal" enum="SuggestionPedalType" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jdonnelly@chromium.org</owner> <owner>orinj@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> @@ -860,7 +860,7 @@ <histogram name="Omnibox.SuggestionUsed.Search.Experimental.NavigationToFirstMeaningfulPaint" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>jdonnelly@chromium.org</owner> <owner>mpearson@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> @@ -895,7 +895,7 @@ </histogram> <histogram name="Omnibox.SuggestionUsed.SelectedTabMatch" - enum="BooleanSelected" expires_after="2022-06-05"> + enum="BooleanSelected" expires_after="2022-08-07"> <owner>gangwu@chromium.org</owner> <owner>mpearson@chromium.org</owner> <owner>jdonnelly@chromium.org</owner> @@ -1127,7 +1127,7 @@ </histogram> <histogram name="Omnibox.ZeroSuggestRequests.NonPrefetch" - enum="OmniboxZeroSuggestRequests" expires_after="2022-06-05"> + enum="OmniboxZeroSuggestRequests" expires_after="2022-08-07"> <owner>mahmadi@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> <summary> @@ -1139,7 +1139,7 @@ </histogram> <histogram name="Omnibox.ZeroSuggestRequests.NonPrefetch.RoundTripTime" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>mahmadi@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> <summary> @@ -1151,7 +1151,7 @@ </histogram> <histogram name="Omnibox.ZeroSuggestRequests.Prefetch" - enum="OmniboxZeroSuggestRequests" expires_after="2022-06-05"> + enum="OmniboxZeroSuggestRequests" expires_after="2022-08-07"> <owner>mahmadi@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> <summary> @@ -1163,7 +1163,7 @@ </histogram> <histogram name="Omnibox.ZeroSuggestRequests.Prefetch.RoundTripTime" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>mahmadi@chromium.org</owner> <owner>chrome-omnibox-team@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/optimization/histograms.xml b/tools/metrics/histograms/metadata/optimization/histograms.xml index 098d66f..2f5b9f5 100644 --- a/tools/metrics/histograms/metadata/optimization/histograms.xml +++ b/tools/metrics/histograms/metadata/optimization/histograms.xml
@@ -975,7 +975,7 @@ </histogram> <histogram name="OptimizationGuide.RemoteFetchingEnabled" - units="BooleanEnabled" expires_after="2022-06-05"> + units="BooleanEnabled" expires_after="2022-08-07"> <owner>sophiechang@chromium.org</owner> <owner>mcrouse@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/others/histograms.xml b/tools/metrics/histograms/metadata/others/histograms.xml index 733dbb4..f34b99b7 100644 --- a/tools/metrics/histograms/metadata/others/histograms.xml +++ b/tools/metrics/histograms/metadata/others/histograms.xml
@@ -1171,7 +1171,7 @@ <histogram name="AutocompleteActionPredictor.PrerenderStatus" enum="AutocompleteActionPredictorPredictionStatus" - expires_after="2022-06-08"> + expires_after="2022-08-07"> <owner>asamidoi@chromium.org</owner> <owner>chrome-prerendering@google.com</owner> <summary> @@ -2792,7 +2792,7 @@ </histogram> <histogram name="ClientHints.AcceptCHFrame" enum="AcceptCHFrameRestart" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>aarontag@chromium.org</owner> <owner>miketaylr@chromium.org</owner> <summary> @@ -2804,7 +2804,7 @@ </histogram> <histogram name="ClientHints.CriticalCHRestart" enum="CriticalCHRestart" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>aarontag@chromium.org</owner> <owner>miketaylr@chromium.org</owner> <summary> @@ -2886,7 +2886,7 @@ </histogram> <histogram name="Clipboard.Read" enum="ClipboardFormatRead" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>huangdarwin@chromium.org</owner> <owner>src/ui/base/clipboard/OWNERS</owner> <summary> @@ -2914,7 +2914,7 @@ </histogram> <histogram name="Clipboard.Write" enum="ClipboardFormatWrite" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>huangdarwin@chromium.org</owner> <owner>src/ui/base/clipboard/OWNERS</owner> <summary> @@ -3164,7 +3164,7 @@ </histogram> <histogram name="ContextMenu.LensChip.Event" enum="LensChipEvent" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>yusuyoutube@google.com</owner> <owner>benwgold@google.com</owner> <summary> @@ -3230,7 +3230,7 @@ </histogram> <histogram base="true" name="ContextMenu.SelectedOptionDesktop" - enum="ContextMenuOptionDesktop" expires_after="2022-06-05"> + enum="ContextMenuOptionDesktop" expires_after="2022-08-07"> <owner>avi@chromium.org</owner> <owner>mpearson@chromium.org</owner> <summary> @@ -3331,7 +3331,7 @@ </histogram> <histogram name="ContextMenu.URLClicked" enum="BooleanClicked" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>twellington@chromium.org</owner> <owner>clank-app-team@google.com</owner> <summary>Logged when the URL is clicked. Android only.</summary> @@ -5144,7 +5144,7 @@ </histogram> <histogram name="ExploreSites.CatalogRequestResult" - enum="ExploreSitesCatalogUpdateRequestResult" expires_after="2022-05-01"> + enum="ExploreSitesCatalogUpdateRequestResult" expires_after="2022-08-07"> <owner>dewittj@chromium.org</owner> <owner>petewil@chromium.org</owner> <summary>Results of the Explore Sites network request for a catalog.</summary> @@ -5437,7 +5437,7 @@ </histogram> <histogram name="Feedback.RequestSource" enum="FeedbackSource" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>afakhry@chromium.org</owner> <owner>cros-telemetry@google.com</owner> <summary>Records the source that requested showing the feedback app.</summary> @@ -5574,7 +5574,7 @@ </histogram> <histogram name="FirstRun.Sentinel.Created" enum="FirstRunSentinelResult" - expires_after="2022-04-01"> + expires_after="2022-08-07"> <owner>jlebel@chromium.org</owner> <owner>chrome-signin-team@google.com</owner> <summary>Result of sentinel file has been written.</summary> @@ -6605,7 +6605,7 @@ </histogram> <histogram base="true" name="JSDialogs.OriginRelationship" - enum="DialogOriginRelationship" expires_after="2022-06-01"> + enum="DialogOriginRelationship" expires_after="2022-08-07"> <owner>avi@chromium.org</owner> <owner>carlosil@chromium.org</owner> <owner>ericmill@google.com</owner> @@ -6617,7 +6617,7 @@ </histogram> <histogram base="true" name="JSDialogs.Scheme" enum="NavigationScheme" - expires_after="2022-06-01"> + expires_after="2022-08-07"> <owner>avi@chromium.org</owner> <owner>carlosil@chromium.org</owner> <owner>ericmill@google.com</owner> @@ -6821,7 +6821,7 @@ </histogram> <histogram name="Kiosk.Launch.CryptohomeFailure" enum="LoginFailureReason" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>xiyuan@chromium.org</owner> <owner>apotapchuk@chromium.org</owner> <summary>Tracks cryptohome failure during kiosk launch.</summary> @@ -7112,7 +7112,7 @@ </histogram> <histogram name="Lens.ImageClassification.ResultState" - enum="LensClassifyResultState" expires_after="2022-06-05"> + enum="LensClassifyResultState" expires_after="2022-08-07"> <owner>yusuyoutube@google.com</owner> <owner>benwgold@google.com</owner> <summary> @@ -7122,7 +7122,7 @@ </histogram> <histogram name="Lens.ImageClassification.SdkError" enum="LensSdkError" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>yusuyoutube@google.com</owner> <owner>benwgold@google.com</owner> <summary> @@ -7133,7 +7133,7 @@ </histogram> <histogram name="Lens.Omnibox.LensSupportStatus" enum="LensSupportStatus" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>yusuyoutube@google.com</owner> <owner>benwgold@google.com</owner> <owner>fgorski@chromium.org</owner> @@ -9092,7 +9092,7 @@ </histogram> <histogram name="PaintHolding.InputTiming2" enum="PaintHoldingInputTiming" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>schenney@chromium.org</owner> <owner>paint-dev@chromium.org</owner> <summary> @@ -10369,7 +10369,7 @@ </histogram> <histogram name="Privacy.AccuracyTip.PageStatus" enum="AccuracyTipStatus" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>dullweber@chromium.org</owner> <owner>eokoyomon@chromium.org</owner> <summary>The accuracy status of a page. Recorded on each page load.</summary> @@ -13336,7 +13336,7 @@ </histogram> <histogram name="SubresourceWebBundles.ContentLength" units="bytes" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>horo@chromium.org</owner> <owner>webpackage-dev@chromium.org</owner> <summary> @@ -13346,14 +13346,14 @@ </histogram> <histogram name="SubresourceWebBundles.LoadResult" - enum="SubresourceWebBundleLoadResult" expires_after="2022-06-05"> + enum="SubresourceWebBundleLoadResult" expires_after="2022-08-07"> <owner>horo@chromium.org</owner> <owner>webpackage-dev@chromium.org</owner> <summary>The result of loading subresource web bundles.</summary> </histogram> <histogram name="SubresourceWebBundles.MaxMemoryUsagePerProcess" units="bytes" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>horo@chromium.org</owner> <owner>webpackage-dev@chromium.org</owner> <summary> @@ -13364,7 +13364,7 @@ </histogram> <histogram name="SubresourceWebBundles.ReceivedSize" units="bytes" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>horo@chromium.org</owner> <owner>webpackage-dev@chromium.org</owner> <summary> @@ -14252,7 +14252,7 @@ </histogram> <histogram name="Tracing.Background.FinalizationDisallowedReason" - enum="TracingFinalizationDisallowedReason" expires_after="2022-06-05"> + enum="TracingFinalizationDisallowedReason" expires_after="2022-08-07"> <owner>ssid@chromium.org</owner> <summary> Reason why background tracing finalization was not allowed. Also see @@ -14288,7 +14288,7 @@ </histogram> <histogram name="Tracing.Background.ScenarioState" - enum="BackgroundTracingState" expires_after="2022-06-05"> + enum="BackgroundTracingState" expires_after="2022-08-07"> <owner>oysteine@chromium.org</owner> <summary> Records state of the Background Tracing system, from when scenarios are @@ -15211,7 +15211,7 @@ </histogram> <histogram name="WebFont.CacheHit" enum="WebFontCacheHit" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>hajimehoshi@chromium.org</owner> <owner>kenjibaheux@chromium.org</owner> <owner>kouhei@chromium.org</owner> @@ -15697,7 +15697,7 @@ </histogram> <histogram name="WhatsNew.LoadEvent" enum="WhatsNewLoadEvent" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>rbpotter@chromium.org</owner> <owner>mahmadi@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/page/histograms.xml b/tools/metrics/histograms/metadata/page/histograms.xml index ebcbc6b0..969aa71 100644 --- a/tools/metrics/histograms/metadata/page/histograms.xml +++ b/tools/metrics/histograms/metadata/page/histograms.xml
@@ -305,7 +305,7 @@ </histogram> <histogram name="PageLoad.Clients.Ads.Resources.Bytes.Ads2" units="KB" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>johnidel@chromium.org</owner> <owner>jkarlin@chromium.org</owner> <summary> @@ -436,7 +436,7 @@ <histogram name="PageLoad.Clients.AMP.LayoutInstability.CumulativeShiftScore.Subframe" - units="scorex10" expires_after="2022-06-05"> + units="scorex10" expires_after="2022-08-07"> <owner>bmcquade@chromium.org</owner> <owner>skobes@chromium.org</owner> <owner>sullivan@chromium.org</owner> @@ -532,7 +532,7 @@ <histogram name="PageLoad.Clients.AMP.PaintTiming.InputToFirstContentfulPaint.Subframe" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>bmcquade@chromium.org</owner> <owner>sullivan@chromium.org</owner> <owner>speed-metrics-dev@chromium.org</owner> @@ -548,7 +548,7 @@ <histogram name="PageLoad.Clients.AMP.PaintTiming.InputToFirstContentfulPaint.Subframe.FullNavigation" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>bmcquade@chromium.org</owner> <owner>sullivan@chromium.org</owner> <owner>speed-metrics-dev@chromium.org</owner> @@ -563,7 +563,7 @@ <histogram name="PageLoad.Clients.AMP.PaintTiming.InputToLargestContentfulPaint.Subframe" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>bmcquade@chromium.org</owner> <owner>sullivan@chromium.org</owner> <owner>speed-metrics-dev@chromium.org</owner> @@ -585,7 +585,7 @@ <histogram name="PageLoad.Clients.AMP.PaintTiming.InputToLargestContentfulPaint.Subframe.FullNavigation" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>bmcquade@chromium.org</owner> <owner>sullivan@chromium.org</owner> <owner>speed-metrics-dev@chromium.org</owner> @@ -1023,7 +1023,7 @@ </histogram> <histogram name="PageLoad.Experimental.Bytes.Network" units="KB" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jkarlin@chromium.org</owner> <summary> The number of prefiltered (e.g., compressed) response body KiloBytes loaded @@ -1328,7 +1328,7 @@ <histogram name="PageLoad.Experimental.PageTiming.CommitSentToFirstSubresourceLoadStart" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>cduvall@chromium.org</owner> <owner>jam@chromium.org</owner> <summary> @@ -1340,7 +1340,7 @@ <histogram name="PageLoad.Experimental.PageTiming.NavigationToFirstSubresourceLoadStart" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>cduvall@chromium.org</owner> <owner>jam@chromium.org</owner> <summary> @@ -1364,7 +1364,7 @@ <histogram name="PageLoad.Experimental.PageTiming.TotalSubresourceLoadTimeAtFirstContentfulPaint" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>cduvall@chromium.org</owner> <owner>jam@chromium.org</owner> <summary> @@ -1452,7 +1452,7 @@ <histogram name="PageLoad.Experimental.PaintTiming.NavigationToFirstEligibleToPaint" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>cduvall@chromium.org</owner> <owner>jam@chromium.org</owner> <summary> @@ -1487,7 +1487,7 @@ </histogram> <histogram name="PageLoad.Experimental.TotalForegroundDuration" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>npm@chromium.org</owner> <owner>speed-metrics-dev@chromium.org</owner> <summary> @@ -2284,7 +2284,7 @@ </histogram> <histogram name="PageLoad.PaintTiming.NavigationToLargestContentfulPaint2" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>npm@chromium.org</owner> <owner>speed-metrics-dev@chromium.org</owner> <summary> @@ -2310,7 +2310,7 @@ <histogram name="PageLoad.PaintTiming.NavigationToLargestContentfulPaint2.MainFrame" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>npm@chromium.org</owner> <owner>speed-metrics-dev@chromium.org</owner> <summary> @@ -2322,7 +2322,7 @@ </histogram> <histogram name="PageLoad.PaintTiming.ParseStartToFirstContentfulPaint" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>bmcquade@chromium.org</owner> <owner>csharrison@chromium.org</owner> <owner>speed-metrics-dev@chromium.org</owner> @@ -2365,7 +2365,7 @@ </histogram> <histogram name="PageLoad.ParseTiming.ParseBlockedOnScriptLoad" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>bmcquade@chromium.org</owner> <owner>csharrison@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/password/histograms.xml b/tools/metrics/histograms/metadata/password/histograms.xml index 212277b..28a103b4 100644 --- a/tools/metrics/histograms/metadata/password/histograms.xml +++ b/tools/metrics/histograms/metadata/password/histograms.xml
@@ -243,7 +243,7 @@ </histogram> <histogram name="PasswordGeneration.SubmissionEvent" - enum="PasswordSubmissionEvent" expires_after="2022-06-05"> + enum="PasswordSubmissionEvent" expires_after="2022-08-07"> <owner>kazinova@google.com</owner> <owner>kolos@chromium.org</owner> <summary> @@ -616,7 +616,7 @@ </histogram> <histogram name="PasswordManager.AffiliationFetcher.FailedToParseResponse" - enum="Boolean" expires_after="2022-04-01"> + enum="Boolean" expires_after="2022-08-07"> <owner>vsemeniuk@google.com</owner> <owner>vasilii@chromium.org</owner> <summary> @@ -658,7 +658,7 @@ </histogram> <histogram name="PasswordManager.AffiliationService.GetChangePasswordUsage" - enum="GetChangePasswordUrlMetric" expires_after="2022-06-05"> + enum="GetChangePasswordUrlMetric" expires_after="2022-08-07"> <owner>vsemeniuk@google.com</owner> <owner>vasilii@chromium.org</owner> <summary> @@ -806,7 +806,7 @@ </histogram> <histogram name="PasswordManager.BiometricAuthPwdFill.AuthRequester" - enum="BiometricAuthRequester" expires_after="2022-06-05"> + enum="BiometricAuthRequester" expires_after="2022-08-07"> <owner>ioanap@chromium.org</owner> <owner>fhorschig@chromium.org</owner> <summary> @@ -817,7 +817,7 @@ </histogram> <histogram name="PasswordManager.BiometricAuthPwdFill.AuthResult" - enum="BiometricAuthResult" expires_after="2022-06-05"> + enum="BiometricAuthResult" expires_after="2022-08-07"> <owner>ioanap@chromium.org</owner> <owner>fhorschig@chromium.org</owner> <summary> @@ -1355,7 +1355,7 @@ </histogram> <histogram name="PasswordManager.FillingSource" - enum="PasswordManagerFillingSource" expires_after="2022-06-05"> + enum="PasswordManagerFillingSource" expires_after="2022-08-07"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -1593,7 +1593,7 @@ </histogram> <histogram name="PasswordManager.LeakDetection.IsPasswordReused" enum="Boolean" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>vasilii@chromium.org</owner> <owner>vsemeniuk@google.com</owner> <summary> @@ -1824,7 +1824,7 @@ </histogram> <histogram name="PasswordManager.PasswordReuse.NumberOfMatches" - units="credentials" expires_after="2022-06-05"> + units="credentials" expires_after="2022-08-07"> <owner>vakh@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -2325,7 +2325,7 @@ </histogram> <histogram name="PasswordManager.StoresUsedForFillingInLast28Days" - enum="PasswordManagerFillingSource" expires_after="2022-06-05"> + enum="PasswordManagerFillingSource" expires_after="2022-08-07"> <owner>mamir@chromium.org</owner> <owner>treib@chromium.org</owner> <summary> @@ -2865,7 +2865,7 @@ </histogram> <histogram name="PasswordProtection.ModalWarningDialogAction" - enum="PasswordProtectionWarningAction" expires_after="2022-06-05"> + enum="PasswordProtectionWarningAction" expires_after="2022-08-07"> <owner>vakh@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/permissions/histograms.xml b/tools/metrics/histograms/metadata/permissions/histograms.xml index 080c4b66..89f955dc 100644 --- a/tools/metrics/histograms/metadata/permissions/histograms.xml +++ b/tools/metrics/histograms/metadata/permissions/histograms.xml
@@ -223,7 +223,7 @@ </histogram> <histogram name="Permissions.CrowdDeny.DidHoldbackQuietUi" enum="Boolean" - expires_after="2022-05-01"> + expires_after="2022-08-07"> <owner>andypaicu@chromium.org</owner> <owner>engedy@chromium.org</owner> <owner>hkamila@chromium.org</owner> @@ -1007,7 +1007,7 @@ </histogram> <histogram name="SiteEngagementService.OriginsEngaged" units="units" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>calamity@chromium.org</owner> <owner>dominickn@chromium.org</owner> <summary> @@ -1055,7 +1055,7 @@ </histogram> <histogram name="WebsiteSettings.Action" enum="WebsiteSettingsAction" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>estark@chromium.org</owner> <owner>dullweber@chromium.org</owner> <summary> @@ -1086,7 +1086,7 @@ </histogram> <histogram name="WebsiteSettings.Discoverability.Action" - enum="WebsiteSettingsDiscoverabilityAction" expires_after="2022-06-05"> + enum="WebsiteSettingsDiscoverabilityAction" expires_after="2022-08-07"> <owner>eokoyomon@chromium.org</owner> <owner>dullweber@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/platform/histograms.xml b/tools/metrics/histograms/metadata/platform/histograms.xml index d92fec8..a4ca1bb 100644 --- a/tools/metrics/histograms/metadata/platform/histograms.xml +++ b/tools/metrics/histograms/metadata/platform/histograms.xml
@@ -187,7 +187,7 @@ </histogram> <histogram name="Platform.Cr50.RlzOfBoardIdMismatch" enum="Cr50CrosRlzCodes" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>vbendeb@chromium.org</owner> <owner>apronin@chromium.org</owner> <owner>cros-hwsec+uma@chromium.org</owner> @@ -448,7 +448,7 @@ </histogram> <histogram name="Platform.IntelMaxMicroArchitecture" - enum="IntelMaxMicroArchitecture" expires_after="2022-06-05"> + enum="IntelMaxMicroArchitecture" expires_after="2022-08-07"> <owner>fbarchard@chromium.org</owner> <owner>pwnall@chromium.org</owner> <summary> @@ -1268,7 +1268,7 @@ </histogram> <histogram name="Platform.TPM.TimeToTakeOwnership" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>yich@google.com</owner> <owner>cylai@google.com</owner> <owner>cros-hwsec+uma@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/power/histograms.xml b/tools/metrics/histograms/metadata/power/histograms.xml index 059402d..b8c1bfe 100644 --- a/tools/metrics/histograms/metadata/power/histograms.xml +++ b/tools/metrics/histograms/metadata/power/histograms.xml
@@ -387,7 +387,7 @@ </histogram> <histogram name="Power.CpuTimeSecondsPerProcessType" enum="ProcessType2" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>eseckler@chromium.org</owner> <owner>skyostil@chromium.org</owner> <summary> @@ -1017,7 +1017,7 @@ </histogram> <histogram name="Power.Mac.IsOnBattery2" enum="BooleanOnBattery" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>avi@chromium.org</owner> <owner>lgrey@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/prefetch/histograms.xml b/tools/metrics/histograms/metadata/prefetch/histograms.xml index 99e4ab1..bd104057 100644 --- a/tools/metrics/histograms/metadata/prefetch/histograms.xml +++ b/tools/metrics/histograms/metadata/prefetch/histograms.xml
@@ -314,7 +314,7 @@ </histogram> <histogram name="PrefetchProxy.SpareRenderer.CountStartedOnSRP" units="count" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>robertogden@chromium.org</owner> <owner>ryansturm@chromium.org</owner> <owner>tbansal@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/printing/histograms.xml b/tools/metrics/histograms/metadata/printing/histograms.xml index 48808df..ba60db1d 100644 --- a/tools/metrics/histograms/metadata/printing/histograms.xml +++ b/tools/metrics/histograms/metadata/printing/histograms.xml
@@ -83,7 +83,7 @@ </histogram> <histogram name="Printing.CUPS.AddressResolutionResult" enum="BooleanSuccess" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>skau@chromium.org</owner> <owner>cros-printing-dev@chromium.org</owner> <summary> @@ -105,7 +105,7 @@ </histogram> <histogram name="Printing.CUPS.IppAttributesSuccess" enum="BooleanSuccess" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>skau@chromium.org</owner> <owner>cros-printing-dev@chromium.org</owner> <summary> @@ -305,7 +305,7 @@ </histogram> <histogram name="Printing.CUPS.UnknownPpdColorModel" enum="Boolean" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>dhoss@chromium.org</owner> <owner>thestig@chromium.org</owner> <summary> @@ -355,7 +355,7 @@ <histogram name="Printing.PrintBackend.DriversRequiringElevatedPrivilegeEncountered" - enum="BooleanFound" expires_after="2022-06-05"> + enum="BooleanFound" expires_after="2022-08-07"> <owner>awscreen@chromium.org</owner> <owner>thestig@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/profile/histograms.xml b/tools/metrics/histograms/metadata/profile/histograms.xml index 2cd3399..a1071a88 100644 --- a/tools/metrics/histograms/metadata/profile/histograms.xml +++ b/tools/metrics/histograms/metadata/profile/histograms.xml
@@ -23,13 +23,13 @@ <histograms> <histogram name="Profile.AddNewUser" enum="ProfileAddNewUser" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>rogerta@chromium.org</owner> <summary>The frequency of ways that new user profiles are added.</summary> </histogram> <histogram name="Profile.AddSignInFlowOutcome" - enum="ProfileAddSignInFlowOutcome" expires_after="2022-06-05"> + enum="ProfileAddSignInFlowOutcome" expires_after="2022-08-07"> <owner>jkrcal@chromium.org</owner> <owner>droger@chromium.org</owner> <summary> @@ -238,7 +238,7 @@ </histogram> <histogram name="Profile.Incognito.Lifetime" units="minutes" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>rhalavati@chromium.org</owner> <owner>chrome-incognito@google.com</owner> <summary> @@ -399,7 +399,7 @@ </histogram> <histogram name="Profile.NumberOfProfiles" units="profiles" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>droger@chromium.org</owner> <owner>jkrcal@chromium.org</owner> <summary> @@ -436,7 +436,7 @@ </histogram> <histogram name="Profile.NumberOfUnusedProfiles" units="profiles" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>msarda@chromium.org</owner> <owner>droger@chromium.org</owner> <summary> @@ -665,7 +665,7 @@ </histogram> <histogram name="ProfilePicker.AskOnStartup" enum="BooleanEnabled" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>msalama@chromium.org</owner> <owner>chrome-signin-team@google.com</owner> <summary> @@ -772,7 +772,7 @@ </histogram> <histogram name="ProfilePicker.StartupTime.FirstPaint.FromApplicationStart" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <owner>alexilin@chromium.org</owner> <owner>dgn@chromium.org</owner> <owner>chrome-signin-team@google.com</owner>
diff --git a/tools/metrics/histograms/metadata/renderer/histograms.xml b/tools/metrics/histograms/metadata/renderer/histograms.xml index 4de9859e..41c713e7 100644 --- a/tools/metrics/histograms/metadata/renderer/histograms.xml +++ b/tools/metrics/histograms/metadata/renderer/histograms.xml
@@ -268,7 +268,7 @@ </histogram> <histogram name="Renderer.Font.PrimaryFont.FCP" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>kojii@chromium.org</owner> <owner>tkent@chromium.org</owner> <owner>yosin@chromium.org</owner> @@ -281,7 +281,7 @@ </histogram> <histogram name="Renderer.Font.PrimaryFont.FCP.Style" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>kojii@chromium.org</owner> <owner>tkent@chromium.org</owner> <owner>yosin@chromium.org</owner> @@ -344,17 +344,6 @@ </summary> </histogram> -<histogram name="Renderer.Hung.MobileInfoBar.UserEvent" - enum="MobileHungRendererInfoBarEvent" expires_after="M85"> - <owner>dfalcantara@chromium.org</owner> - <summary> - Android: Records the terminal event associated with a hung renderer infobar. - This includes both the explicit user actions as well as implicit dismissals, - e.g., when the renderer regains responsiveness before the infobar is - interactively dismissed. - </summary> -</histogram> - <histogram name="Renderer.PaintPreview.Capture.MainFrameBlinkCaptureDuration" units="ms" expires_after="2022-06-12"> <owner>ckitagawa@chromium.org</owner> @@ -432,16 +421,6 @@ <token key="Lifetime" variants="RendererLifetime"/> </histogram> -<histogram name="Renderer.ViewportZoomBugCount" enum="BooleanHit" - expires_after="M77"> - <owner>kkhorimoto@chromium.org</owner> - <summary> - [iOS] A boolean that is used to indicate that the WebKit rendering bug in - http://crbug.com/583231 has occurred. This occurs when a page with no - viewport tag is rendered with an unusable zoom scale. Only logged on iOS. - </summary> -</histogram> - <histogram name="RendererScheduler.IPC.FrameVisibility" enum="Boolean" expires_after="M85"> <owner>altimin@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/renderer4/histograms.xml b/tools/metrics/histograms/metadata/renderer4/histograms.xml index d1e5d0fe..2916ab3 100644 --- a/tools/metrics/histograms/metadata/renderer4/histograms.xml +++ b/tools/metrics/histograms/metadata/renderer4/histograms.xml
@@ -195,7 +195,7 @@ </histogram> <histogram name="Renderer4.MainThreadWheelScrollReason" - enum="MainThreadScrollingReason" expires_after="2022-06-05"> + enum="MainThreadScrollingReason" expires_after="2022-08-07"> <owner>flackr@chromium.org</owner> <owner>pdr@chromium.org</owner> <owner>input-dev@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml index e646c29..cb7e756 100644 --- a/tools/metrics/histograms/metadata/safe_browsing/histograms.xml +++ b/tools/metrics/histograms/metadata/safe_browsing/histograms.xml
@@ -1042,7 +1042,7 @@ <histogram name="SafeBrowsing.ExtensionTelemetry.NetworkRequestResponseCodeOrError" - enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-06-01"> + enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-08-07"> <owner>anunoy@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -1056,7 +1056,7 @@ </histogram> <histogram name="SafeBrowsing.ExtensionTelemetry.RetriesTillUploadSuccess" - units="retries" expires_after="2022-06-01"> + units="retries" expires_after="2022-08-07"> <owner>anunoy@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -1803,7 +1803,7 @@ </histogram> <histogram base="true" name="SafeBrowsing.Settings.UserAction" - enum="SafeBrowsingSettingsUserAction" expires_after="2022-06-05"> + enum="SafeBrowsingSettingsUserAction" expires_after="2022-08-07"> <owner>xinghuilu@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -2309,7 +2309,7 @@ </histogram> <histogram name="SafeBrowsing.V4Update.Network.Result" - enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-06-05"> + enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-08-07"> <owner>vakh@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -2334,7 +2334,7 @@ </histogram> <histogram name="SafeBrowsing.V4Update.ResponseSizeKB" units="KB" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>vakh@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/sb_client/histograms.xml b/tools/metrics/histograms/metadata/sb_client/histograms.xml index b2ee716..a943a5b3 100644 --- a/tools/metrics/histograms/metadata/sb_client/histograms.xml +++ b/tools/metrics/histograms/metadata/sb_client/histograms.xml
@@ -475,7 +475,7 @@ </histogram> <histogram name="SBClientPhishing.FlatBufferMappedRegionValid" - enum="BooleanSuccess" expires_after="2022-06-05"> + enum="BooleanSuccess" expires_after="2022-08-07"> <owner>bhatiarohit@google.com</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -608,7 +608,7 @@ </histogram> <histogram name="SBClientPhishing.ProtobufScorer.CreationStatus" - enum="SBClientPhishingScorerCreationStatus" expires_after="2022-06-05"> + enum="SBClientPhishingScorerCreationStatus" expires_after="2022-08-07"> <owner>bhatiarohit@google.com</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary> @@ -713,7 +713,7 @@ </histogram> <histogram name="SBClientPhishing.VisualComparisonTime" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>drubery@chromium.org</owner> <owner>chrome-safebrowsing-alerts@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/search/histograms.xml b/tools/metrics/histograms/metadata/search/histograms.xml index 9eb64a6b..2fec138 100644 --- a/tools/metrics/histograms/metadata/search/histograms.xml +++ b/tools/metrics/histograms/metadata/search/histograms.xml
@@ -44,7 +44,7 @@ </histogram> <histogram name="Search.ContextualSearch.All.Searches" - enum="BooleanBottomSearchKind" expires_after="2022-06-05"> + enum="BooleanBottomSearchKind" expires_after="2022-08-07"> <!-- TODO(donnd): change expires_after to never once established and approved. --> @@ -232,7 +232,7 @@ </histogram> <histogram name="Search.ContextualSearch.ResolveRequested" - enum="ContextualSearchGestureIsTap" expires_after="2022-06-05"> + enum="ContextualSearchGestureIsTap" expires_after="2022-08-07"> <owner>donnd@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -243,7 +243,7 @@ </histogram> <histogram name="Search.ContextualSearch.SelectionExpanded" - enum="ContextualSearchGestureIsTap" expires_after="2022-06-05"> + enum="ContextualSearchGestureIsTap" expires_after="2022-08-07"> <owner>donnd@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -848,7 +848,7 @@ </histogram> <histogram name="Search.ContextualSearchQuickActions.Category" - enum="ContextualSearchQuickActionCategory" expires_after="2022-06-05"> + enum="ContextualSearchQuickActionCategory" expires_after="2022-08-07"> <owner>donnd@chromium.org</owner> <owner>twellington@chromium.org</owner> <summary> @@ -1206,7 +1206,7 @@ </histogram> <histogram name="Search.DefaultSearchProviderType" - enum="OmniboxSearchEngineType" expires_after="2022-06-05"> + enum="OmniboxSearchEngineType" expires_after="2022-08-07"> <owner>mpearson@chromium.org</owner> <owner>csharp@chromium.org</owner> <summary> @@ -1334,28 +1334,28 @@ </histogram> <histogram name="Search.QueryTiles.Fetcher.Start" units="hours" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>qinmin@chromium.org</owner> <owner>chrome-upboarding-eng@google.com</owner> <summary>Records the hour (0-23) when the TileFetcher task starts.</summary> </histogram> <histogram name="Search.QueryTiles.FetcherHttpResponseCode" - enum="HttpResponseCode" expires_after="2022-06-05"> + enum="HttpResponseCode" expires_after="2022-08-07"> <owner>qinmin@chromium.org</owner> <owner>chrome-upboarding-eng@google.com</owner> <summary>Records the HTTP response code get from TileFetcher.</summary> </histogram> <histogram name="Search.QueryTiles.FetcherNetErrorCode" enum="NetErrorCodes" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>qinmin@chromium.org</owner> <owner>chrome-upboarding-eng@google.com</owner> <summary>Records the net error code get from TileFetcher.</summary> </histogram> <histogram name="Search.QueryTiles.Group.PruneReason" - enum="QueryTilesGroupPruneReason" expires_after="2022-06-05"> + enum="QueryTilesGroupPruneReason" expires_after="2022-08-07"> <owner>qinmin@chromium.org</owner> <owner>chrome-upboarding-eng@google.com</owner> <summary> @@ -1364,7 +1364,7 @@ </histogram> <histogram name="Search.QueryTiles.GroupStatus" enum="QueryTilesGroupStatus" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>qinmin@chromium.org</owner> <owner>chrome-upboarding-eng@google.com</owner> <summary> @@ -1484,7 +1484,7 @@ </histogram> <histogram name="Search.QueryTiles.TrendingTileEvent" enum="TrendingTileEvent" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>qinmin@chromium.org</owner> <owner>chrome-upboarding-eng@google.com</owner> <summary> @@ -1623,7 +1623,7 @@ </histogram> <histogram name="Search.RelatedSearches.SelectedCarouselIndex" units="position" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>donnd@chromium.org</owner> <owner>related-searches-vteam@google.com</owner> <summary> @@ -1634,7 +1634,7 @@ </histogram> <histogram name="Search.RelatedSearches.SelectedSuggestionIndex" - units="position" expires_after="2022-06-05"> + units="position" expires_after="2022-08-07"> <owner>donnd@chromium.org</owner> <owner>related-searches-vteam@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/security/histograms.xml b/tools/metrics/histograms/metadata/security/histograms.xml index b8628b1..2751f3ca 100644 --- a/tools/metrics/histograms/metadata/security/histograms.xml +++ b/tools/metrics/histograms/metadata/security/histograms.xml
@@ -327,7 +327,7 @@ </histogram> <histogram name="Security.SafetyTips.Interaction" enum="SafetyTipInteraction" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jdeblasio@chromium.org</owner> <owner>estark@chromium.org</owner> <summary> @@ -788,7 +788,7 @@ </histogram> <histogram name="SiteIsolation.IsPasswordFormSubmittedInDedicatedProcess" - enum="SiteIsolationIsDedicatedProcess" expires_after="2022-06-05"> + enum="SiteIsolationIsDedicatedProcess" expires_after="2022-08-07"> <owner>alexmos@chromium.org</owner> <owner>lukasza@chromium.org</owner> <summary> @@ -910,7 +910,7 @@ </histogram> <histogram name="SiteIsolation.SavedOAuthSites.Size" units="origins" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>alexmos@chromium.org</owner> <owner>creis@chromium.org</owner> <owner>lukasza@chromium.org</owner> @@ -922,7 +922,7 @@ </histogram> <histogram name="SiteIsolation.SavedUserTriggeredIsolatedOrigins.Size" - units="origins" expires_after="2022-06-05"> + units="origins" expires_after="2022-08-07"> <owner>alexmos@chromium.org</owner> <owner>creis@chromium.org</owner> <owner>lukasza@chromium.org</owner> @@ -935,7 +935,7 @@ </histogram> <histogram name="SiteIsolation.SavedWebTriggeredIsolatedOrigins.Size" - units="origins" expires_after="2022-06-05"> + units="origins" expires_after="2022-08-07"> <owner>alexmos@chromium.org</owner> <owner>creis@chromium.org</owner> <owner>lukasza@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/service/histograms.xml b/tools/metrics/histograms/metadata/service/histograms.xml index f0cb04cf..679332f 100644 --- a/tools/metrics/histograms/metadata/service/histograms.xml +++ b/tools/metrics/histograms/metadata/service/histograms.xml
@@ -248,14 +248,14 @@ </histogram> <histogram name="ServiceWorker.Database.ReadResult" - enum="ServiceWorkerDatabaseStatus" expires_after="2022-06-05"> + enum="ServiceWorkerDatabaseStatus" expires_after="2022-08-07"> <owner>bashi@chromium.org</owner> <owner>nhiroki@chromium.org</owner> <summary>Records result of read operations in ServiceWorkerDatabase.</summary> </histogram> <histogram name="ServiceWorker.Database.WriteResult" - enum="ServiceWorkerDatabaseStatus" expires_after="2022-06-05"> + enum="ServiceWorkerDatabaseStatus" expires_after="2022-08-07"> <owner>bashi@chromium.org</owner> <owner>nhiroki@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/session/histograms.xml b/tools/metrics/histograms/metadata/session/histograms.xml index 58c4aff..6d04c7a 100644 --- a/tools/metrics/histograms/metadata/session/histograms.xml +++ b/tools/metrics/histograms/metadata/session/histograms.xml
@@ -659,7 +659,7 @@ </histogram> <histogram name="SessionRestore.UnrecoverableWriteErrorCount" - units="operations" expires_after="2022-06-05"> + units="operations" expires_after="2022-08-07"> <owner>sky@chromium.org</owner> <owner>davidbienvenu@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/settings/histograms.xml b/tools/metrics/histograms/metadata/settings/histograms.xml index 60e8957..f6f91fc 100644 --- a/tools/metrics/histograms/metadata/settings/histograms.xml +++ b/tools/metrics/histograms/metadata/settings/histograms.xml
@@ -288,7 +288,7 @@ </histogram> <histogram name="Settings.SafetyCheck.SafeBrowsingResult" - enum="SafetyCheckSafeBrowsingStatus" expires_after="2022-06-05"> + enum="SafetyCheckSafeBrowsingStatus" expires_after="2022-08-07"> <owner>andzaytsev@google.com</owner> <owner>msramek@chromium.org</owner> <summary>Resulting state of the safety check Safe Browsing check.</summary>
diff --git a/tools/metrics/histograms/metadata/sharing/histograms.xml b/tools/metrics/histograms/metadata/sharing/histograms.xml index e25b2e7..7f827e5 100644 --- a/tools/metrics/histograms/metadata/sharing/histograms.xml +++ b/tools/metrics/histograms/metadata/sharing/histograms.xml
@@ -388,7 +388,7 @@ </histogram> <histogram name="Sharing.SendAckMessageResult" enum="SharingSendMessageResult" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <!-- Name completed by histogram_suffixes name="SharingChannelType", name="SharingDevicePlatform" and name="SharingMessage" --> @@ -401,7 +401,7 @@ </histogram> <histogram name="Sharing.SendMessageResult" enum="SharingSendMessageResult" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <!-- Name completed by histogram_suffixes SharingChannelType, SharingDevicePlatform, SharingMessage, and SharingPulseInterval. -->
diff --git a/tools/metrics/histograms/metadata/signin/histograms.xml b/tools/metrics/histograms/metadata/signin/histograms.xml index b17d604..de73ebc 100644 --- a/tools/metrics/histograms/metadata/signin/histograms.xml +++ b/tools/metrics/histograms/metadata/signin/histograms.xml
@@ -95,7 +95,7 @@ </histogram> <histogram name="Signin.AccountConsistencyPromoAction" - enum="AccountConsistencyPromoAction" expires_after="2022-06-05"> + enum="AccountConsistencyPromoAction" expires_after="2022-08-07"> <owner>bsazonov@chromium.org</owner> <owner>aliceywang@chromium.org</owner> <summary> @@ -147,7 +147,7 @@ </histogram> <histogram name="Signin.AccountReconcilorState.OnGaiaResponse" - enum="SigninAccountReconcilorState" expires_after="2022-06-05"> + enum="SigninAccountReconcilorState" expires_after="2022-08-07"> <owner>jlebel@chromium.org</owner> <owner>chrome-signin-team@google.com</owner> <summary> @@ -172,7 +172,7 @@ </histogram> <histogram name="Signin.AccountTracker.GaiaIdMigrationState" - enum="OAuth2LoginAccountRevokedMigrationState" expires_after="2022-06-05"> + enum="OAuth2LoginAccountRevokedMigrationState" expires_after="2022-08-07"> <owner>msarda@chromium.org</owner> <owner>sdefresne@chromium.org</owner> <summary> @@ -190,7 +190,7 @@ </histogram> <histogram name="Signin.AccountType.SigninConsent" enum="SigninAccountType" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jlebel@chromium.org</owner> <owner>chrome-signin-team@chromium.org</owner> <summary> @@ -200,7 +200,7 @@ </histogram> <histogram name="Signin.AccountType.SyncConsent" enum="SigninAccountType" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jlebel@chromium.org</owner> <owner>chrome-signin-team@chromium.org</owner> <summary> @@ -442,7 +442,7 @@ </histogram> <histogram name="Signin.GetAccessTokenFinished" enum="GoogleServiceAuthError" - expires_after="2022-04-19"> + expires_after="2022-08-07"> <owner>droger@chromium.org</owner> <owner>msarda@chromium.org</owner> <summary> @@ -621,7 +621,7 @@ </histogram> <histogram name="Signin.IOSNumberOfDeviceAccounts" units="accounts" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jlebel@chromium.org</owner> <owner>msarda@chromium.org</owner> <owner>chrome-signin-team@google.com</owner> @@ -674,7 +674,7 @@ </histogram> <histogram name="Signin.LoadedIdentities.Count" units="identities" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jlebel@chromium.org</owner> <owner>msarda@chromium.org</owner> <owner>chrome-signin-team@google.com</owner> @@ -954,7 +954,7 @@ </histogram> <histogram name="Signin.SignedInAccountsViewImpression" enum="BooleanShown" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>jlebel@chromium.org</owner> <owner>msarda@chromium.org</owner> <owner>chrome-signin-team@google.com</owner> @@ -1035,7 +1035,7 @@ </histogram> <histogram name="Signin.SSOAuth.GetIdentities.ErrorCode" - enum="SigninSSOAuthGetIdentitiesErrorCode" expires_after="2022-06-05"> + enum="SigninSSOAuthGetIdentitiesErrorCode" expires_after="2022-08-07"> <owner>jlebel@chromium.org</owner> <owner>chrome-signin-team@google.com</owner> <summary> @@ -1148,7 +1148,7 @@ </histogram> <histogram name="Signin.SyncFirstSetupCompleteSource" - enum="SyncFirstSetupCompleteSource" expires_after="2022-06-05"> + enum="SyncFirstSetupCompleteSource" expires_after="2022-08-07"> <owner>triploblastic@chromium.org</owner> <owner>bsazonov@chromium.org</owner> <summary>Tracks where FirstSetupComplete bit is set from.</summary> @@ -1203,7 +1203,7 @@ </histogram> <histogram name="Signin.TransactionalReauthResult" enum="SigninReauthResult" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <!-- Name completed by histogram_suffixes name="TransactionalReauthEntryPoint" --> @@ -1257,7 +1257,7 @@ </histogram> <histogram name="Signin.UserRequestedWipeDataOnSignout" enum="BooleanRequested" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>triploblastic@google.com</owner> <owner>bsazonov@chromium.org</owner> <summary>User requested to wipe local device data on signout.</summary>
diff --git a/tools/metrics/histograms/metadata/stability/histograms.xml b/tools/metrics/histograms/metadata/stability/histograms.xml index cccd1bc..6293bf65 100644 --- a/tools/metrics/histograms/metadata/stability/histograms.xml +++ b/tools/metrics/histograms/metadata/stability/histograms.xml
@@ -389,7 +389,7 @@ </histogram> <histogram name="Stability.IOS.UTE.AppWillTerminateWasCalledInForeground" - enum="Boolean" expires_after="2022-06-06"> + enum="Boolean" expires_after="2022-08-07"> <owner>olivierrobin@chromium.org</owner> <owner>ajuma@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/startup/histograms.xml b/tools/metrics/histograms/metadata/startup/histograms.xml index 5810f92..81089351 100644 --- a/tools/metrics/histograms/metadata/startup/histograms.xml +++ b/tools/metrics/histograms/metadata/startup/histograms.xml
@@ -177,7 +177,7 @@ </histogram> <histogram name="Startup.Android.Cold.TimeToVisibleContent" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>yashard@chromium.org</owner> <owner>ckitagawa@chromium.org</owner> <summary> @@ -294,7 +294,7 @@ </histogram> <histogram base="true" name="Startup.Android.SingleTabTitleAvailableTime" - units="ms" expires_after="2022-06-05"> + units="ms" expires_after="2022-08-07"> <!-- Name completed by histogram_suffixes name="JavaStartMode" --> <owner>hanxi@chromium.org</owner> @@ -419,7 +419,7 @@ </histogram> <histogram name="Startup.BringToForegroundReason" - enum="BooleanBringToForegroundReason" expires_after="2022-06-05"> + enum="BooleanBringToForegroundReason" expires_after="2022-08-07"> <owner>peter@chromium.org</owner> <summary> Records the cause, each time Chrome is brought to the foreground. Currently @@ -801,7 +801,7 @@ </histogram> <histogram name="Startup.MobileSessionStartFromApps" - enum="MobileSessionCallerApp" expires_after="2022-06-05"> + enum="MobileSessionCallerApp" expires_after="2022-08-07"> <owner>thegreenfrog@chromium.org</owner> <owner>olivierrobin@chromium.org</owner> <summary>The calling application (if any).</summary>
diff --git a/tools/metrics/histograms/metadata/subresource/histograms.xml b/tools/metrics/histograms/metadata/subresource/histograms.xml index f9d39cb..7901419b 100644 --- a/tools/metrics/histograms/metadata/subresource/histograms.xml +++ b/tools/metrics/histograms/metadata/subresource/histograms.xml
@@ -480,7 +480,7 @@ </histogram> <histogram name="SubresourceFilter.PageLoad.NumSubresourceLoads.MatchedRules" - units="resource loads" expires_after="2022-06-05"> + units="resource loads" expires_after="2022-08-07"> <owner>jkarlin@chromium.org</owner> <owner>chrome-ads-histograms@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/sync/histograms.xml b/tools/metrics/histograms/metadata/sync/histograms.xml index 173c9f5..0cd16e7c 100644 --- a/tools/metrics/histograms/metadata/sync/histograms.xml +++ b/tools/metrics/histograms/metadata/sync/histograms.xml
@@ -107,7 +107,7 @@ </histogram> <histogram name="Sync.BookmarkGUIDSource2" enum="BookmarkGUIDSource" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>rushans@google.com</owner> <owner>mastiz@chromium.org</owner> <component>Services>Sync</component> @@ -121,7 +121,7 @@ </histogram> <histogram name="Sync.BookmarkModelMerger.ReachableInputUpdates" - units="bookmarks" expires_after="2022-06-05"> + units="bookmarks" expires_after="2022-08-07"> <owner>rushans@google.com</owner> <owner>mastiz@chromium.org</owner> <component>Services>Sync</component> @@ -187,7 +187,7 @@ </histogram> <histogram name="Sync.BookmarkSpecificsExcludingFoldersContainFavicon" - enum="Boolean" expires_after="2022-06-05"> + enum="Boolean" expires_after="2022-08-07"> <owner>rushans@google.com</owner> <owner>mastiz@chromium.org</owner> <component>Services>Sync</component> @@ -527,7 +527,7 @@ </histogram> <histogram name="Sync.ModelTypeBlockedDueToUndecryptableUpdate" - enum="SyncModelTypes" expires_after="2022-06-05"> + enum="SyncModelTypes" expires_after="2022-08-07"> <owner>victorvianna@google.com</owner> <owner>mastiz@chromium.org</owner> <component>Services>Sync</component> @@ -637,7 +637,7 @@ </histogram> <histogram name="Sync.ModelTypeInitialUpdateReceived" enum="SyncModelTypes" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>rushans@google.com</owner> <owner>mastiz@chromium.org</owner> <component>Services>Sync</component> @@ -897,7 +897,7 @@ </histogram> <histogram name="Sync.ProblematicServerSideBookmarksDuringMerge" - enum="RemoteBookmarkUpdateError" expires_after="2022-06-05"> + enum="RemoteBookmarkUpdateError" expires_after="2022-08-07"> <owner>rushans@google.com</owner> <owner>mastiz@chromium.org</owner> <component>Services>Sync</component> @@ -997,7 +997,7 @@ </histogram> <histogram name="Sync.StopSource" enum="SyncStopSource" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>treib@chromium.org</owner> <owner>mastiz@chromium.org</owner> <component>Services>Sync</component> @@ -1041,7 +1041,7 @@ </histogram> <histogram name="Sync.SyncEverything2" enum="Boolean" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>treib@chromium.org</owner> <owner>mastiz@chromium.org</owner> <component>Services>Sync</component> @@ -1054,7 +1054,7 @@ </histogram> <histogram name="Sync.SyncStoppedReported" enum="Boolean" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>rushans@google.com</owner> <owner>treib@chromium.org</owner> <component>Services>Sync</component> @@ -1067,7 +1067,7 @@ </histogram> <histogram name="Sync.SyncStoppedURLFetchResponse" - enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-06-05"> + enum="CombinedHttpResponseAndNetErrorCode" expires_after="2022-08-07"> <owner>rushans@google.com</owner> <owner>treib@chromium.org</owner> <component>Services>Sync</component>
diff --git a/tools/metrics/histograms/metadata/tab/histograms.xml b/tools/metrics/histograms/metadata/tab/histograms.xml index e9fe42fd..584a23a 100644 --- a/tools/metrics/histograms/metadata/tab/histograms.xml +++ b/tools/metrics/histograms/metadata/tab/histograms.xml
@@ -68,7 +68,7 @@ </variants> <histogram name="Discarding.DiscardCandidatesCount" units="tabs" - expires_after="2022-05-01"> + expires_after="2022-08-07"> <owner>chrisha@chromium.org</owner> <owner>catan-team@chromium.org</owner> <summary> @@ -374,7 +374,7 @@ </summary> </histogram> -<histogram name="Tab.NewTab" enum="NewTabType" expires_after="2022-06-05"> +<histogram name="Tab.NewTab" enum="NewTabType" expires_after="2022-08-07"> <owner>tbergquist@chromium.org</owner> <owner>bsep@chromium.org</owner> <summary> @@ -644,7 +644,7 @@ </histogram> <histogram name="Tab.StateAtRendererTermination" enum="TabForegroundState" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>gambard@chromium.org</owner> <owner>olivierrobin@chromium.org</owner> <summary> @@ -746,7 +746,7 @@ </histogram> <histogram name="TabGroups.CollapsedGroupCountPerLoad" units="groups" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>connily@chromium.org</owner> <owner>chrome-desktop-ui-sea@google.com</owner> <summary> @@ -776,7 +776,7 @@ </histogram> <histogram name="TabGroups.SessionsPerGroup" units="sessions" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>yusufo@chromium.org</owner> <owner>wychen@chromium.org</owner> <summary> @@ -2391,7 +2391,7 @@ </histogram> <histogram name="Tabs.TabSearch.NumTabsClosedPerInstance" units="tabs" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>tluk@chromium.org</owner> <owner>robliao@chromium.org</owner> <summary> @@ -2404,7 +2404,7 @@ </histogram> <histogram name="Tabs.TabSearch.NumTabsOnOpen" units="tabs" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>tluk@chromium.org</owner> <owner>robliao@chromium.org</owner> <summary> @@ -2442,7 +2442,7 @@ </histogram> <histogram name="Tabs.TabSearch.PageHandlerConstructionDelay" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>tluk@chromium.org</owner> <owner>robliao@chromium.org</owner> <owner>yuhengh@chromium.org</owner> @@ -2599,7 +2599,7 @@ </histogram> <histogram name="Tabs.TabSearch.WebUI.TabListDataReceived" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>tluk@chromium.org</owner> <owner>robliao@chromium.org</owner> <owner>yuhengh@chromium.org</owner> @@ -2643,7 +2643,7 @@ </histogram> <histogram name="Tabs.TabSearch.WindowDisplayedDuration3" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>tluk@chromium.org</owner> <owner>robliao@chromium.org</owner> <summary> @@ -2685,7 +2685,7 @@ </histogram> <histogram name="Tabs.TabSearch.WindowTimeToShowUncachedWebView" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>tluk@chromium.org</owner> <owner>robliao@chromium.org</owner> <owner>yuhengh@chromium.org</owner> @@ -3007,7 +3007,7 @@ </histogram> <histogram name="TabStrip.TimeToCreateNewTabFromPress" units="ms" - expires_after="2022-05-01"> + expires_after="2022-08-07"> <owner>robliao@chromium.org</owner> <owner>chrome-desktop-ui-sea@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/ukm/histograms.xml b/tools/metrics/histograms/metadata/ukm/histograms.xml index d05432f..aa4833e 100644 --- a/tools/metrics/histograms/metadata/ukm/histograms.xml +++ b/tools/metrics/histograms/metadata/ukm/histograms.xml
@@ -214,6 +214,25 @@ </summary> </histogram> +<histogram name="UKM.PrunedSource.{Type}" units="sources" + expires_after="2022-07-01"> + <owner>rkaplow@chromium.org</owner> + <owner>src/base/metrics/OWNERS</owner> + <summary> + Number of sources pruned after the operation of {Type} type. + </summary> + <token key="Type"> + <variant name="AppExpNumAppId" + summary="APP_ID only when not in seen/unseen experiment"/> + <variant name="AppExpNumNonAppId" summary="All non-APP_ID"/> + <variant name="NoExp" summary="Total pruned without experimentation"/> + <variant name="NumAppId" + summary="APP_ID only under seen/unseen experiment"/> + <variant name="NumSeen" summary="Seen only"/> + <variant name="NumUnseen" summary="Unseen only"/> + </token> +</histogram> + <histogram name="UKM.ReportSize.NonUkmPercentage" units="%" expires_after="2022-07-01"> <owner>yrsun@chromium.org</owner>
diff --git a/tools/metrics/histograms/metadata/uma/histograms.xml b/tools/metrics/histograms/metadata/uma/histograms.xml index 8e36cd67..6ccd4c56 100644 --- a/tools/metrics/histograms/metadata/uma/histograms.xml +++ b/tools/metrics/histograms/metadata/uma/histograms.xml
@@ -256,7 +256,7 @@ </histogram> <histogram name="UMA.JavaCachingRecorder.DroppedHistogramSampleCount" - units="samples" expires_after="2022-06-05"> + units="samples" expires_after="2022-08-07"> <owner>bttk@chromium.org</owner> <owner>src/base/metrics/OWNERS</owner> <summary> @@ -267,7 +267,7 @@ </histogram> <histogram name="UMA.JavaCachingRecorder.DroppedUserActionCount" - units="samples" expires_after="2022-06-05"> + units="samples" expires_after="2022-08-07"> <owner>bttk@chromium.org</owner> <owner>src/base/metrics/OWNERS</owner> <summary> @@ -726,7 +726,7 @@ </histogram> <histogram name="UMA.TruncatedEvents.UserAction" units="events" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>rkaplow@chromium.org</owner> <owner>src/base/metrics/OWNERS</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/v8/histograms.xml b/tools/metrics/histograms/metadata/v8/histograms.xml index 4d7c76a..36003ef 100644 --- a/tools/metrics/histograms/metadata/v8/histograms.xml +++ b/tools/metrics/histograms/metadata/v8/histograms.xml
@@ -351,7 +351,7 @@ </histogram> <histogram name="V8.DebugFeatureUsage" enum="V8DebugFeature" - expires_after="2022-04-24"> + expires_after="2022-08-07"> <owner>yangguo@chromium.org</owner> <owner>bmeurer@chromium.org</owner> <summary> @@ -744,7 +744,7 @@ </summary> </histogram> -<histogram name="V8.GCBackgroundSweeping" units="ms" expires_after="2022-06-05"> +<histogram name="V8.GCBackgroundSweeping" units="ms" expires_after="2022-08-07"> <owner>mlippautz@chromium.org</owner> <owner>v8-memory-sheriffs@google.com</owner> <summary> @@ -839,7 +839,7 @@ </histogram> <histogram name="V8.GCFinalizeMC.Prologue" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>mlippautz@chromium.org</owner> <owner>hpayer@chromium.org</owner> <owner>v8-memory-sheriffs@google.com</owner> @@ -921,7 +921,7 @@ </histogram> <histogram name="V8.GCIncrementalMarkingFinalize" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>hpayer@chromium.org</owner> <owner>v8-memory-sheriffs@google.com</owner> <summary>Time spent in finalizing incremental marking.</summary> @@ -981,14 +981,14 @@ </summary> </histogram> -<histogram name="V8.GCScavenger" units="ms" expires_after="2022-06-05"> +<histogram name="V8.GCScavenger" units="ms" expires_after="2022-08-07"> <owner>hpayer@chromium.org</owner> <owner>v8-memory-sheriffs@google.com</owner> <summary>Time spent in scavenging phase of GC.</summary> </histogram> <histogram name="V8.GCScavenger.ScavengeMain" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>mlippautz@chromium.org</owner> <owner>v8-memory-sheriffs@google.com</owner> <summary> @@ -998,7 +998,7 @@ </histogram> <histogram name="V8.GCScavenger.ScavengeRoots" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>mlippautz@chromium.org</owner> <owner>v8-memory-sheriffs@google.com</owner> <summary>Time spent in scavenging the roots during a V8 scavenge.</summary> @@ -1021,7 +1021,7 @@ </histogram> <histogram name="V8.GCScavengerForeground" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>hpayer@chromium.org</owner> <owner>v8-memory-sheriffs@google.com</owner> <summary> @@ -1168,7 +1168,7 @@ </histogram> <histogram name="V8.TurboFanOptimizeConcurrentTotalTime" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>bmeurer@chromium.org</owner> <owner>mslekova@chromium.org</owner> <summary> @@ -1180,7 +1180,7 @@ </histogram> <histogram name="V8.TurboFanOptimizeExecute" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> @@ -1192,7 +1192,7 @@ </histogram> <histogram name="V8.TurboFanOptimizeFinalize" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> @@ -1204,7 +1204,7 @@ </histogram> <histogram name="V8.TurboFanOptimizeForOnStackReplacementExecute" - units="microseconds" expires_after="2022-06-05"> + units="microseconds" expires_after="2022-08-07"> <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> @@ -1217,7 +1217,7 @@ </histogram> <histogram name="V8.TurboFanOptimizeForOnStackReplacementFinalize" - units="microseconds" expires_after="2022-06-05"> + units="microseconds" expires_after="2022-08-07"> <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> @@ -1230,7 +1230,7 @@ </histogram> <histogram name="V8.TurboFanOptimizeForOnStackReplacementPrepare" - units="microseconds" expires_after="2022-06-05"> + units="microseconds" expires_after="2022-08-07"> <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> @@ -1243,7 +1243,7 @@ </histogram> <histogram name="V8.TurboFanOptimizeForOnStackReplacementTotalTime" - units="microseconds" expires_after="2022-06-05"> + units="microseconds" expires_after="2022-08-07"> <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> @@ -1256,7 +1256,7 @@ </histogram> <histogram name="V8.TurboFanOptimizeNonConcurrentTotalTime" - units="microseconds" expires_after="2022-06-05"> + units="microseconds" expires_after="2022-08-07"> <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <owner>mslekova@chromium.org</owner> @@ -1269,7 +1269,7 @@ </histogram> <histogram name="V8.TurboFanOptimizePrepare" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> @@ -1281,7 +1281,7 @@ </histogram> <histogram name="V8.TurboFanOptimizeTotalBackground" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> @@ -1293,7 +1293,7 @@ </histogram> <histogram name="V8.TurboFanOptimizeTotalForeground" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> @@ -1305,7 +1305,7 @@ </histogram> <histogram name="V8.TurboFanOptimizeTotalTime" units="microseconds" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/variations/histograms.xml b/tools/metrics/histograms/metadata/variations/histograms.xml index c3870da..f1ebf2b5 100644 --- a/tools/metrics/histograms/metadata/variations/histograms.xml +++ b/tools/metrics/histograms/metadata/variations/histograms.xml
@@ -63,7 +63,7 @@ </histogram> <histogram name="Variations.ExtendedSafeMode.BeaconFileDeserializationError" - enum="JsonDeserializationError" expires_after="2022-06-05"> + enum="JsonDeserializationError" expires_after="2022-08-07"> <owner>caitlinfischer@google.com</owner> <owner>src/base/metrics/OWNERS</owner> <component>Internals>Metrics>Variations</component> @@ -78,7 +78,7 @@ </histogram> <histogram name="Variations.ExtendedSafeMode.BeaconFileStateAtStartup" - enum="BeaconFileState" expires_after="2022-06-05"> + enum="BeaconFileState" expires_after="2022-08-07"> <owner>caitlinfischer@google.com</owner> <owner>src/base/metrics/OWNERS</owner> <component>Internals>Metrics>Variations</component> @@ -104,7 +104,7 @@ </histogram> <histogram name="Variations.ExtendedSafeMode.WritePrefsTime" - units="microseconds" expires_after="2022-06-05"> + units="microseconds" expires_after="2022-08-07"> <owner>caitlinfischer@google.com</owner> <owner>src/base/metrics/OWNERS</owner> <component>Internals>Metrics>Variations</component>
diff --git a/tools/metrics/histograms/metadata/video_tutorials/histograms.xml b/tools/metrics/histograms/metadata/video_tutorials/histograms.xml index 5491653..22e68d1 100644 --- a/tools/metrics/histograms/metadata/video_tutorials/histograms.xml +++ b/tools/metrics/histograms/metadata/video_tutorials/histograms.xml
@@ -32,7 +32,7 @@ </variants> <histogram name="VideoTutorials.LanguagePicker.Action" - enum="VideoTutorials.LanguagePickerAction" expires_after="2022-06-05"> + enum="VideoTutorials.LanguagePickerAction" expires_after="2022-08-07"> <owner>shaktisahu@chromium.org</owner> <owner>chrome-upboarding-eng@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/web_apk/histograms.xml b/tools/metrics/histograms/metadata/web_apk/histograms.xml index d9406ef6..f3b0153 100644 --- a/tools/metrics/histograms/metadata/web_apk/histograms.xml +++ b/tools/metrics/histograms/metadata/web_apk/histograms.xml
@@ -59,7 +59,7 @@ </histogram> <histogram name="WebApk.Install.GooglePlayErrorCode" - enum="WebApkInstallGooglePlayErrorCode" expires_after="2022-05-01"> + enum="WebApkInstallGooglePlayErrorCode" expires_after="2022-08-07"> <owner>hartmanng@chromium.org</owner> <owner> src/chrome/android/java/src/org/chromium/chrome/browser/webapps/OWNERS
diff --git a/tools/metrics/histograms/metadata/web_rtc/histograms.xml b/tools/metrics/histograms/metadata/web_rtc/histograms.xml index 2233180a..81b2303 100644 --- a/tools/metrics/histograms/metadata/web_rtc/histograms.xml +++ b/tools/metrics/histograms/metadata/web_rtc/histograms.xml
@@ -200,7 +200,7 @@ </histogram> <histogram name="WebRTC.Audio.Agc.InputClippingRate" units="%" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>silen@chromium.org</owner> <owner>alessiob@chromium.org</owner> <owner>minyue@chromium.org</owner> @@ -280,7 +280,7 @@ </histogram> <histogram name="WebRTC.Audio.AgcClippingAdjustmentAllowed" enum="Boolean" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>hlundin@chromium.org</owner> <summary> The automatic gain control (AGC) in WebRTC tries to adjust the microphone @@ -293,7 +293,7 @@ </histogram> <histogram name="WebRTC.Audio.AgcSetLevel" units="level" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>hlundin@chromium.org</owner> <summary> The automatic gain control (AGC) in WebRTC tries to adjust the microphone @@ -814,7 +814,7 @@ </histogram> <histogram name="WebRTC.Audio.SpeechExpandRatePercent" units="%" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>hlundin@chromium.org</owner> <summary> Measures the audible expand rate for an incoming WebRTC audio stream. The @@ -1884,7 +1884,7 @@ </histogram> <histogram name="WebRTC.ReceivedAudioTrackDuration" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>perkj@chromium.org</owner> <summary> Durations of audio tracks received over a PeerConnection. The stopwatch @@ -1894,7 +1894,7 @@ </histogram> <histogram name="WebRTC.ReceivedVideoTrackDuration" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>perkj@chromium.org</owner> <summary> Durations of video tracks received over a PeerConnection. The stopwatch @@ -2010,7 +2010,7 @@ </histogram> <histogram name="WebRTC.SentAudioTrackDuration" units="ms" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>perkj@chromium.org</owner> <summary> Durations of audio tracks sent over a PeerConnection. The stopwatch starts
diff --git a/tools/metrics/histograms/metadata/webapps/histograms.xml b/tools/metrics/histograms/metadata/webapps/histograms.xml index dfa7869..6a1724d 100644 --- a/tools/metrics/histograms/metadata/webapps/histograms.xml +++ b/tools/metrics/histograms/metadata/webapps/histograms.xml
@@ -167,7 +167,7 @@ </histogram> <histogram name="Webapp.AddToHomescreenMediator.AppTypeToMenuEntry" - enum="AppTypeToMenuEntry" expires_after="2022-06-05"> + enum="AppTypeToMenuEntry" expires_after="2022-08-07"> <owner>finnur@chromium.org</owner> <owner>peter@chromium.org</owner> <summary> @@ -391,7 +391,7 @@ </histogram> <histogram name="Webapp.Install.InstallBounce" enum="WebappInstallSource" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>alancutter@chromium.org</owner> <owner>dominickn@chromium.org</owner> <summary> @@ -495,6 +495,22 @@ </summary> </histogram> +<histogram name="WebApp.Preinstalled.AppDuplicationFixApplied" units="apps" + expires_after="2022-07-27"> + <owner>alancutter@chromium.org</owner> + <owner>desktop-pwas-team@google.com</owner> + <summary> + Chrome apps migrated to preinstalled web apps encountered an issue where + apps became duplicated, see https://crbug.com/1266234. + + The PreinstalledWebAppDuplicationFixer was added to fix users that + encountered duplicate apps. See https://crbug.com/1290716. This metric + records how many app duplications got fixed. + + This gets recorded at start up after Chrome apps have loaded. + </summary> +</histogram> + <histogram name="WebApp.Preinstalled.AppToReplaceStillDefaultInstalledCount" units="apps" expires_after="2022-04-17"> <owner>alancutter@chromium.org</owner> @@ -545,7 +561,7 @@ </histogram> <histogram name="WebApp.Preinstalled.ConfigErrorCount" units="apps" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>alancutter@chromium.org</owner> <owner>desktop-pwas-team@google.com</owner> <summary>
diff --git a/tools/metrics/histograms/metadata/webauthn/histograms.xml b/tools/metrics/histograms/metadata/webauthn/histograms.xml index a7b9e4a..8b0e0a0 100644 --- a/tools/metrics/histograms/metadata/webauthn/histograms.xml +++ b/tools/metrics/histograms/metadata/webauthn/histograms.xml
@@ -42,7 +42,7 @@ </histogram> <histogram name="WebAuthentication.CableV2.DiscoveryEvent" - enum="WebAuthenticationCableV2DiscoveryEvent" expires_after="2022-06-05"> + enum="WebAuthenticationCableV2DiscoveryEvent" expires_after="2022-08-07"> <owner>agl@chromium.org</owner> <owner>martinkr@google.com</owner> <summary> @@ -62,7 +62,7 @@ </histogram> <histogram name="WebAuthentication.CableV2.MobileEvent" - enum="WebAuthenticationCableV2MobileEvent" expires_after="2022-06-05"> + enum="WebAuthenticationCableV2MobileEvent" expires_after="2022-08-07"> <owner>agl@chromium.org</owner> <owner>martinkr@google.com</owner> <summary> @@ -72,7 +72,7 @@ </histogram> <histogram name="WebAuthentication.CableV2.MobileResult" - enum="WebAuthenticationCableV2MobileResult" expires_after="2022-06-05"> + enum="WebAuthenticationCableV2MobileResult" expires_after="2022-08-07"> <owner>agl@chromium.org</owner> <owner>martinkr@google.com</owner> <summary>Records the outcome of caBLEv2 transactions.</summary>
diff --git a/tools/metrics/histograms/metadata/xr/histograms.xml b/tools/metrics/histograms/metadata/xr/histograms.xml index d8009bd..667fc14 100644 --- a/tools/metrics/histograms/metadata/xr/histograms.xml +++ b/tools/metrics/histograms/metadata/xr/histograms.xml
@@ -58,7 +58,7 @@ </summary> </histogram> -<histogram name="VRViewerType" enum="VRViewerType" expires_after="2022-06-05"> +<histogram name="VRViewerType" enum="VRViewerType" expires_after="2022-08-07"> <owner>alcooper@chromium.org</owner> <owner>xr-dev@chromium.org</owner> <summary>The type of headset being used for VR.</summary> @@ -85,7 +85,7 @@ </histogram> <histogram name="XR.WebXR.ReferenceSpace.Succeeded" enum="XRReferenceSpaceType" - expires_after="2022-06-05"> + expires_after="2022-08-07"> <owner>alcooper@chromium.org</owner> <owner>xr-dev@chromium.org</owner> <summary>
diff --git a/ui/accessibility/extensions/colorenhancer/src/background.js b/ui/accessibility/extensions/colorenhancer/src/background.js index 17e653c..10213b8 100644 --- a/ui/accessibility/extensions/colorenhancer/src/background.js +++ b/ui/accessibility/extensions/colorenhancer/src/background.js
@@ -47,13 +47,13 @@ * @private */ updateTabs_() { - this.forEachTab_(async (tab) => { + this.forEachTab_((tab) => { const msg = { - 'delta': await this.storage_.getSiteDelta(Common.siteFromUrl(tab.url)), - 'severity': await this.storage_.getDefaultSeverity(), - 'type': await this.storage_.getDefaultType(), - 'simulate': await this.storage_.getDefaultSimulate(), - 'enable': await this.storage_.getDefaultEnable() + 'delta': this.storage_.getSiteDelta(Common.siteFromUrl(tab.url)), + 'severity': this.storage_.getDefaultSeverity(), + 'type': this.storage_.getDefaultType(), + 'simulate': this.storage_.getDefaultSimulate(), + 'enable': this.storage_.getDefaultEnable() }; Common.debugPrint( 'updateTabs: sending ' + JSON.stringify(msg) + ' to ' + @@ -63,21 +63,20 @@ } /** @private */ - async onInitReceived_(sender) { + onInitReceived_(sender) { let delta; if (sender.tab) { - delta = - await this.storage_.getSiteDelta(Common.siteFromUrl(sender.tab.url)); + delta = this.storage_.getSiteDelta(Common.siteFromUrl(sender.tab.url)); } else { - delta = await this.storage_.getDefaultDelta(); + delta = this.storage_.getDefaultDelta(); } return { 'delta': delta, - 'severity': await this.storage_.getDefaultSeverity(), - 'type': await this.storage_.getDefaultType(), - 'simulate': await this.storage_.getDefaultSimulate(), - 'enable': await this.storage_.getDefaultEnable() + 'severity': this.storage_.getDefaultSeverity(), + 'type': this.storage_.getDefaultType(), + 'simulate': this.storage_.getDefaultSimulate(), + 'enable': this.storage_.getDefaultEnable() }; } @@ -91,16 +90,15 @@ chrome.runtime.onMessage.addListener( (message, sender, sendResponse) => { if (message === 'init') { - this.onInitReceived_(sender).then(sendResponse); + this.onInitReceived_(sender); + sendResponse(); return true; // Keep message context open for async response. } else if (message === 'updateTabs') { this.updateTabs_(); } }); chrome.storage.onChanged.addListener(this.updateTabs_.bind(this)); - //TODO(mustaq): Handle uninstall - } }
diff --git a/ui/accessibility/extensions/colorenhancer/src/popup.js b/ui/accessibility/extensions/colorenhancer/src/popup.js index 1482352..68e585e 100644 --- a/ui/accessibility/extensions/colorenhancer/src/popup.js +++ b/ui/accessibility/extensions/colorenhancer/src/popup.js
@@ -125,8 +125,8 @@ * Update the popup controls based on settings for this site or the default. * @return {boolean} True if settings are valid and update performed. */ - async update() { - const type = await storage.getDefaultType(); + update() { + const type = storage.getDefaultType(); let validType = false; Object.values(CvdType).forEach((cvdType) => { if (cvdType == type) { @@ -139,21 +139,21 @@ return false; if (this.site) { - Common.$('delta').value = await storage.getSiteDelta(this.site); + Common.$('delta').value = storage.getSiteDelta(this.site); } else { - Common.$('delta').value = await storage.getDefaultDelta(); + Common.$('delta').value = storage.getDefaultDelta(); } - Common.$('severity').value = await storage.getDefaultSeverity(); + Common.$('severity').value = storage.getDefaultSeverity(); if (!Common.$('setup-panel').classList.contains('collapsed')) - this.setCvdTypeSelection(await storage.getDefaultType()); - Common.$('enable').checked = await storage.getDefaultEnable(); + this.setCvdTypeSelection(storage.getDefaultType()); + Common.$('enable').checked = storage.getDefaultEnable(); Common.debugPrint( 'update: ' + ' del=' + Common.$('delta').value + ' sev=' + - Common.$('severity').value + ' typ=' + await storage.getDefaultType() + + Common.$('severity').value + ' typ=' + storage.getDefaultType() + ' enb=' + Common.$('enable').checked + ' for ' + this.site); chrome.runtime.sendMessage('updateTabs'); return true; @@ -167,9 +167,11 @@ onDeltaChange(value) { Common.debugPrint('onDeltaChange: ' + value + ' for ' + this.site); if (this.site) { - storage.setSiteDelta(this.site, value).then(this.update.bind(this)); + storage.setSiteDelta(this.site, value); + this.update(); } - storage.setDefaultDelta(value).then(this.update.bind(this)); + storage.setDefaultDelta(value); + this.update(); } /** @@ -179,15 +181,14 @@ */ onSeverityChange(value) { Common.debugPrint('onSeverityChange: ' + value + ' for ' + this.site); - storage.setDefaultSeverity(value).then(() => { - this.update(); - // Apply filter to popup swatches. - const filter = - cvd.getDefaultCvdCorrectionFilter(this.getCvdTypeSelection(), value); - cvd.injectColorEnhancementFilter(filter); - // Force a refresh. - window.getComputedStyle(document.documentElement, null); - }); + storage.setDefaultSeverity(value); + this.update(); + // Apply filter to popup swatches. + const filter = + cvd.getDefaultCvdCorrectionFilter(this.getCvdTypeSelection(), value); + cvd.injectColorEnhancementFilter(filter); + // Force a refresh. + window.getComputedStyle(document.documentElement, null); } /** @@ -197,11 +198,10 @@ */ onTypeChange(value) { Common.debugPrint('onTypeChange: ' + value + ' for ' + this.site); - storage.setDefaultType(value).then(() => { - this.update(); - Common.$('severity').value = 0; - this.updateControls(); - }); + storage.setDefaultType(value); + this.update(); + Common.$('severity').value = 0; + this.updateControls(); } /** @@ -211,12 +211,11 @@ */ onEnableChange(value) { Common.debugPrint('onEnableChange: ' + value + ' for ' + this.site); - storage.setDefaultEnable(value).then(() => { - if (!this.update()) { - // Settings are not valid for a reconfiguration. - Common.$('setup').onclick(); - } - }); + storage.setDefaultEnable(value); + if (!this.update()) { + // Settings are not valid for a reconfiguration. + Common.$('setup').onclick(); + } } /** @@ -231,12 +230,12 @@ elem.textContent = chrome.i18n.getMessage(msg); } - Common.$('setup').onclick = async () => { + Common.$('setup').onclick = () => { Common.$('setup-panel').classList.remove('collapsed'); // Store current settings in the event of a canceled setup. this.restoreSettings = { - type: await storage.getDefaultType(), - severity: await storage.getDefaultSeverity() + type: storage.getDefaultType(), + severity: storage.getDefaultSeverity() }; // Initialize controls based on current settings. this.setCvdTypeSelection(this.restoreSettings.type);
diff --git a/ui/accessibility/extensions/colorenhancer/src/storage.js b/ui/accessibility/extensions/colorenhancer/src/storage.js index c840988..e2468f0 100644 --- a/ui/accessibility/extensions/colorenhancer/src/storage.js +++ b/ui/accessibility/extensions/colorenhancer/src/storage.js
@@ -3,7 +3,6 @@ // found in the LICENSE file. // TODO(wnwen): Wrap calls. -// TODO(anastasi): Change interface to remove unneeded promises. /** @typedef {CvdType|number|boolean} */ let StoredValue; @@ -124,62 +123,50 @@ return delta >= 0 && delta <= 1; } - /** @return {Promise<number>} */ + /** @return {number} */ getDefaultDelta() { - return new Promise(resolve => { - resolve(this.defaultDelta_); - }); + return this.defaultDelta_; } /** * @param {number} delta - * @return {Promise} */ setDefaultDelta(delta) { if (!this.validDelta_(delta)) { delta = Storage.DEFAULT_DELTA; } this.defaultDelta_ = delta; - return new Promise( - resolve => this.store_(Storage.DELTA_TAG, delta, resolve)); + this.store_(Storage.DELTA_TAG, delta); } /** * @param {string} site - * @return {Promise<number>} + * @return {number} */ getSiteDelta(site) { - return new Promise(resolve => { - const delta = this.siteDeltas_[site]; - if (!this.validDelta_(delta)) { - this.setSiteDelta(site, this.defaultDelta_); - resolve(this.defaultDelta_); - return; - } - resolve(delta); - }); + const delta = this.siteDeltas_[site]; + if (!this.validDelta_(delta)) { + this.setSiteDelta(site, this.defaultDelta_); + return this.defaultDelta_; + } + return delta; } /** * @param {string} site * @param {number} delta - * @return {Promise} */ setSiteDelta(site, delta) { - return new Promise(resolve => { - if (!this.validDelta_(delta)) { - delta = this.defaultDelta_; - } - this.siteDeltas_[site] = delta; - this.store_(Storage.PER_SITE_DELTA_TAG, this.siteDeltas_, resolve); - }); + if (!this.validDelta_(delta)) { + delta = this.defaultDelta_; + } + this.siteDeltas_[site] = delta; + this.store_(Storage.PER_SITE_DELTA_TAG, this.siteDeltas_); } - /** @return {Promise} */ resetSiteDeltas() { this.siteDeltas_ = {}; - return new Promise( - resolve => this.store_(Storage.PER_SITE_DELTA_TAG, {}, resolve)); + this.store_(Storage.PER_SITE_DELTA_TAG, {}); } // ======= Severity setting ======= @@ -193,24 +180,20 @@ return severity >= 0 && severity <= 1; } - /** @return {Promise<number>} */ + /** @return {number} */ getDefaultSeverity() { - return new Promise(resolve => { - resolve(this.defaultSeverity_); - }); + return this.defaultSeverity_; } /** * @param {number} severity - * @return {Promise} */ setDefaultSeverity(severity) { if (!this.validSeverity_(severity)) { severity = Storage.DEFAULT_SEVERITY; } this.defaultSeverity_ = severity; - return new Promise( - resolve => this.store_(Storage.SEVERITY_TAG, severity, resolve)); + this.store_(Storage.SEVERITY_TAG, severity); } // ======= Type setting ======= @@ -224,67 +207,56 @@ return Object.values(CvdType).includes(type); } - /** @return {Promise<!CvdType|Storage.INVALID_TYPE_PLACEHOLDER>} */ + /** @return {!CvdType|Storage.INVALID_TYPE_PLACEHOLDER} */ getDefaultType() { - return new Promise(resolve => { - resolve(this.defaultType_); - }); + return this.defaultType_; } /** * @param {CvdType} type - * @return {Promise} */ setDefaultType(type) { if (!this.validType_(type)) { type = Storage.INVALID_TYPE_PLACEHOLDER; } this.defaultType_ = type; - return new Promise(resolve => this.store_(Storage.TYPE_TAG, type, resolve)); + this.store_(Storage.TYPE_TAG, type); } // ======= Simulate setting ======= - /** @return {Promise<boolean>} */ + /** @return {boolean} */ getDefaultSimulate() { - return new Promise(resolve => { - resolve(this.defaultSimulate_); - }); + return this.defaultSimulate_; } /** * @param {boolean} simulate - * @return {Promise} */ setDefaultSimulate(simulate) { if (!this.validBoolean_(simulate)) { simulate = Storage.DEFAULT_SIMULATE; } this.defaultSimulate_ = simulate; - return new Promise( - resolve => this.store_(Storage.SIMULATE_TAG, simulate, resolve)); + this.store_(Storage.SIMULATE_TAG, simulate); } // ======= Enable setting ======= - /** @return {Promise<boolean>} */ + /** @return {boolean} */ getDefaultEnable() { - return new Promise(resolve => { - resolve(this.defaultEnable_); - }); + return this.defaultEnable_; } /** * @param {boolean} enable - * @return {Promise} */ setDefaultEnable(enable) { if (!this.validBoolean_(enable)) { enable = Storage.DEFAULT_ENABLE; } this.defaultEnable_ = enable; - return new Promise( - resolve => this.store_(Storage.ENABLE_TAG, enable, resolve)); + this.store_(Storage.ENABLE_TAG, enable); } // ======= Helper functions ======== @@ -300,13 +272,13 @@ /** * @param {*} key * @param {*} val - * @param {function()} callback + * @param {function()|undefined} opt_callback * @private */ - store_(key, val, callback) { + store_(key, val, opt_callback) { const newVals = {}; newVals[key] = val; - chrome.storage.local.set(newVals, callback); + chrome.storage.local.set(newVals, opt_callback); } }
diff --git a/ui/accessibility/platform/ax_platform_node_base.cc b/ui/accessibility/platform/ax_platform_node_base.cc index 0f981c5..febb5d6 100644 --- a/ui/accessibility/platform/ax_platform_node_base.cc +++ b/ui/accessibility/platform/ax_platform_node_base.cc
@@ -138,6 +138,12 @@ return nullptr; } +AXPlatformNodeBase* AXPlatformNodeBase::GetPlatformTextFieldAncestor() const { + if (delegate_) + return FromNativeViewAccessible(delegate_->GetTextFieldAncestor()); + return nullptr; +} + int AXPlatformNodeBase::GetChildCount() const { if (delegate_) return delegate_->GetChildCount();
diff --git a/ui/accessibility/platform/ax_platform_node_base.h b/ui/accessibility/platform/ax_platform_node_base.h index 3ffdaf2f..8aa7e9d 100644 --- a/ui/accessibility/platform/ax_platform_node_base.h +++ b/ui/accessibility/platform/ax_platform_node_base.h
@@ -112,6 +112,8 @@ AXPlatformNodeBase* GetLastChild() const; bool IsDescendant(AXPlatformNodeBase* descendant); + AXPlatformNodeBase* GetPlatformTextFieldAncestor() const; + using AXPlatformNodeChildIterator = ui::AXNode::ChildIteratorBase<AXPlatformNodeBase, &AXPlatformNodeBase::GetNextSibling,
diff --git a/ui/accessibility/platform/ax_platform_node_cocoa.mm b/ui/accessibility/platform/ax_platform_node_cocoa.mm index db54f8e7..6afd5d3f 100644 --- a/ui/accessibility/platform/ax_platform_node_cocoa.mm +++ b/ui/accessibility/platform/ax_platform_node_cocoa.mm
@@ -6,6 +6,8 @@ #import <Cocoa/Cocoa.h> +#include "base/logging.h" + #include "base/mac/foundation_util.h" #include "base/no_destructor.h" #include "base/strings/sys_string_conversions.h" @@ -784,8 +786,14 @@ // Caret navigation and text selection attributes. if (!ui::IsPlatformDocument(_node->GetRole())) { - [axAttributes - addObjectsFromArray:@[ NSAccessibilityFocusableAncestorAttribute ]]; + [axAttributes addObject:NSAccessibilityFocusableAncestorAttribute]; + + if (_node->HasState(ax::mojom::State::kEditable)) { + [axAttributes addObjectsFromArray:@[ + NSAccessibilityEditableAncestorAttribute, + NSAccessibilityHighestEditableAncestorAttribute + ]]; + } } // Live regions. @@ -1102,6 +1110,16 @@ return nil; } +- (id)AXEditableAncestor { + if (![self instanceActive]) + return nil; + ui::AXPlatformNodeBase* text_field_ancestor = + _node->GetPlatformTextFieldAncestor(); + if (text_field_ancestor) + return text_field_ancestor->GetNativeViewAccessible(); + return nil; +} + - (NSNumber*)AXElementBusy { if (![self instanceActive]) return nil; @@ -1124,6 +1142,24 @@ return @(_node->HasIntAttribute(ax::mojom::IntAttribute::kHasPopup)); } +- (id)AXHighestEditableAncestor { + if (![self instanceActive]) + return nil; + + AXPlatformNodeCocoa* highestEditableAncestor = [self AXEditableAncestor]; + + while (highestEditableAncestor) { + AXPlatformNodeCocoa* ancestorParent = [highestEditableAncestor AXParent]; + if (!ancestorParent || ![ancestorParent isKindOfClass:[self class]]) + break; + AXPlatformNodeCocoa* higherAncestor = [ancestorParent AXEditableAncestor]; + if (!higherAncestor) + break; + highestEditableAncestor = higherAncestor; + } + return highestEditableAncestor; +} + - (NSString*)AXInvalid { if (![self instanceActive]) return nil;
diff --git a/ui/accessibility/platform/ax_private_attributes_mac.h b/ui/accessibility/platform/ax_private_attributes_mac.h index 044957ab..875508e 100644 --- a/ui/accessibility/platform/ax_private_attributes_mac.h +++ b/ui/accessibility/platform/ax_private_attributes_mac.h
@@ -46,6 +46,8 @@ @"AXDOMIdentifier"; AX_EXPORT constexpr NSString* const NSAccessibilityDropEffectsAttribute = @"AXDropEffects"; +AX_EXPORT constexpr NSString* const NSAccessibilityEditableAncestorAttribute = + @"AXEditableAncestor"; AX_EXPORT constexpr NSString* const NSAccessibilityElementBusyAttribute = @"AXElementBusy"; AX_EXPORT constexpr NSString* const NSAccessibilityFocusableAncestorAttribute = @@ -54,6 +56,9 @@ @"AXGrabbed"; AX_EXPORT constexpr NSString* const NSAccessibilityHasPopupAttribute = @"AXHasPopup"; +AX_EXPORT constexpr NSString* const + NSAccessibilityHighestEditableAncestorAttribute = + @"AXHighestEditableAncestor"; AX_EXPORT constexpr NSString* const NSAccessibilityInvalidAttribute = @"AXInvalid"; AX_EXPORT constexpr NSString* const NSAccessibilityIsMultiSelectable =
diff --git a/ui/accessibility/platform/fuchsia/semantic_provider.h b/ui/accessibility/platform/fuchsia/semantic_provider.h index 5be3d66..1b3d876 100644 --- a/ui/accessibility/platform/fuchsia/semantic_provider.h +++ b/ui/accessibility/platform/fuchsia/semantic_provider.h
@@ -67,7 +67,7 @@ virtual bool Delete(uint32_t node_id) = 0; // Clears the semantic tree. - virtual bool Clear(); + virtual bool Clear() = 0; // Sends an accessibility event to Fuchsia. Please consult // https://cs.opensource.google/fuchsia/fuchsia/+/master:sdk/fidl/fuchsia.accessibility.semantics/semantics_manager.fidl
diff --git a/ui/android/BUILD.gn b/ui/android/BUILD.gn index 43aa634..0a59dd20 100644 --- a/ui/android/BUILD.gn +++ b/ui/android/BUILD.gn
@@ -249,6 +249,7 @@ "java/src/org/chromium/ui/base/ApplicationViewportInsetSupplier.java", "java/src/org/chromium/ui/base/Clipboard.java", "java/src/org/chromium/ui/base/DeviceFormFactor.java", + "java/src/org/chromium/ui/base/DragAndDropDelegateImpl.java", "java/src/org/chromium/ui/base/DropDataAndroid.java", "java/src/org/chromium/ui/base/EventForwarder.java", "java/src/org/chromium/ui/base/EventOffsetHandler.java",
diff --git a/ui/android/java/res/values-night/colors.xml b/ui/android/java/res/values-night/colors.xml index acdbd6c5..513873e 100644 --- a/ui/android/java/res/values-night/colors.xml +++ b/ui/android/java/res/values-night/colors.xml
@@ -14,6 +14,7 @@ <color name="default_text_color_error">@color/default_text_color_error_light</color> <color name="default_text_color_on_accent1_baseline">@color/default_text_color_on_accent1_dark</color> <color name="default_text_color_on_accent1_disabled_baseline">@color/default_text_color_disabled_light</color> + <color name="default_text_color_on_accent2_container_baseline">@color/baseline_secondary_100</color> <!-- Common icon colors for drawables. --> <color name="default_icon_color_baseline">@color/default_icon_color_light</color>
diff --git a/ui/android/java/res/values/color_palette.xml b/ui/android/java/res/values/color_palette.xml index 26df560c..73a83917 100644 --- a/ui/android/java/res/values/color_palette.xml +++ b/ui/android/java/res/values/color_palette.xml
@@ -68,6 +68,7 @@ <color name="baseline_secondary_300">#5AB3F0</color> <color name="baseline_secondary_300_with_neutral_100_alpha_8">#53A7E1</color> <color name="baseline_secondary_300_with_neutral_100_alpha_24">#448FC4</color> + <color name="baseline_secondary_700">#004A77</color> <color name="baseline_secondary_900">#001D35</color> <color name="baseline_tertiary_100">#C4EED0</color> <color name="baseline_tertiary_200">#6DD58C</color>
diff --git a/ui/android/java/res/values/semantic_colors_adaptive.xml b/ui/android/java/res/values/semantic_colors_adaptive.xml index efae08a..c0692acc 100644 --- a/ui/android/java/res/values/semantic_colors_adaptive.xml +++ b/ui/android/java/res/values/semantic_colors_adaptive.xml
@@ -19,10 +19,7 @@ <color name="default_text_color_error">@color/default_text_color_error_dark</color> <color name="default_text_color_on_accent1_baseline">@color/default_text_color_on_accent1_light</color> <color name="default_text_color_on_accent1_disabled_baseline">@color/default_text_color_disabled_dark</color> - <!-- TODO(https://crbug.com/1248157): This is the same as light mode's - ?attr/colorOnSecondaryContainer, but it would break in dark mode. - Figure out a solution for dynamic colors. --> - <color name="default_text_color_on_accent2_container">@color/baseline_secondary_900</color> + <color name="default_text_color_on_accent2_container_baseline">@color/baseline_secondary_900</color> <!-- Common icon colors for drawables. --> <color name="default_icon_color_baseline">@color/default_icon_color_dark</color>
diff --git a/ui/android/java/src/org/chromium/ui/base/DragAndDropDelegateImpl.java b/ui/android/java/src/org/chromium/ui/base/DragAndDropDelegateImpl.java new file mode 100644 index 0000000..3219b5c --- /dev/null +++ b/ui/android/java/src/org/chromium/ui/base/DragAndDropDelegateImpl.java
@@ -0,0 +1,43 @@ +// Copyright 2022 The Chromium 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.ui.base; + +import android.content.ClipData; +import android.graphics.Bitmap; +import android.os.Build.VERSION_CODES; +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; + +import org.chromium.base.compat.ApiHelperForN; + +/** + * Drag and drop helper class in charge of building the clip data, wrapping calls to + * {@link android.view.View#startDragAndDrop}. Also used for mocking out real function calls to + * Android. + */ +class DragAndDropDelegateImpl implements ViewAndroidDelegate.DragAndDropDelegate { + /** + * Wrapper to call {@link android.view.View#startDragAndDrop}. + * @see ViewAndroidDelegate#startDragAndDrop(Bitmap, DropDataAndroid) + * */ + @Override + @RequiresApi(api = VERSION_CODES.N) + public boolean startDragAndDrop( + @NonNull View view, @NonNull Bitmap shadowImage, @NonNull DropDataAndroid dropData) { + ImageView imageView = new ImageView(view.getContext()); + imageView.setImageBitmap(shadowImage); + imageView.layout(0, 0, shadowImage.getWidth(), shadowImage.getHeight()); + + return ApiHelperForN.startDragAndDrop(view, buildClipData(dropData), + new View.DragShadowBuilder(imageView), null, View.DRAG_FLAG_GLOBAL); + } + + protected ClipData buildClipData(DropDataAndroid dropData) { + return ClipData.newPlainText(null, dropData.text); + } +}
diff --git a/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java b/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java index 7471c8e8..3a786a90 100644 --- a/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java +++ b/ui/android/java/src/org/chromium/ui/base/ViewAndroidDelegate.java
@@ -16,7 +16,6 @@ import android.view.ViewGroup; import android.view.ViewGroup.MarginLayoutParams; import android.view.inputmethod.InputConnection; -import android.widget.ImageView; import androidx.annotation.VisibleForTesting; import androidx.core.view.MarginLayoutParamsCompat; @@ -33,6 +32,16 @@ @JNINamespace("ui") public class ViewAndroidDelegate { /** + * Delegate to re-route the call to {@link #startDragAndDrop(Bitmap, DropDataAndroid).} + */ + public interface DragAndDropDelegate { + boolean startDragAndDrop(View containerView, Bitmap shadowImage, DropDataAndroid dropData); + } + + private static DragAndDropDelegate sDragAndDropTestDelegate; + private DragAndDropDelegate mDragAndDropDelegate; + + /** * The current container view. This view can be updated with * {@link #setContainerView()}. */ @@ -59,6 +68,8 @@ protected ViewAndroidDelegate(ViewGroup containerView) { mContainerView = containerView; + mDragAndDropDelegate = sDragAndDropTestDelegate != null ? sDragAndDropTestDelegate + : new DragAndDropDelegateImpl(); } /** @@ -181,12 +192,7 @@ ViewGroup containerView = getContainerViewGroup(); if (containerView == null) return false; - ImageView imageView = new ImageView(containerView.getContext()); - imageView.setImageBitmap(shadowImage); - imageView.layout(0, 0, shadowImage.getWidth(), shadowImage.getHeight()); - String text = dropData.text; - return ApiHelperForN.startDragAndDrop(containerView, ClipData.newPlainText(null, text), - new View.DragShadowBuilder(imageView), null, View.DRAG_FLAG_GLOBAL); + return mDragAndDropDelegate.startDragAndDrop(containerView, shadowImage, dropData); } @VisibleForTesting @@ -491,4 +497,9 @@ protected int[] getDisplayFeature() { return null; } + + @VisibleForTesting + public static void setDragAndDropDelegateForTest(DragAndDropDelegate testDelegate) { + sDragAndDropTestDelegate = testDelegate; + } }
diff --git a/ui/android/java/src/org/chromium/ui/widget/RippleBackgroundHelper.java b/ui/android/java/src/org/chromium/ui/widget/RippleBackgroundHelper.java index 32125f1..62b3b0e 100644 --- a/ui/android/java/src/org/chromium/ui/widget/RippleBackgroundHelper.java +++ b/ui/android/java/src/org/chromium/ui/widget/RippleBackgroundHelper.java
@@ -11,6 +11,8 @@ import android.graphics.drawable.InsetDrawable; import android.graphics.drawable.LayerDrawable; import android.graphics.drawable.RippleDrawable; +import android.os.Build.VERSION; +import android.os.Build.VERSION_CODES; import android.util.StateSet; import android.view.View; @@ -21,7 +23,6 @@ import androidx.annotation.Px; import androidx.appcompat.content.res.AppCompatResources; import androidx.core.graphics.ColorUtils; -import androidx.core.view.ViewCompat; import org.chromium.ui.R; @@ -40,13 +41,11 @@ private final View mView; private @Nullable ColorStateList mBackgroundColorList; + private @Nullable ColorStateList mStateLayerColorList; private GradientDrawable mBackgroundGradient; - - // Used for applying tint on pre-L versions. - private Drawable mBackgroundDrawablePreL; - private Drawable mRippleDrawablePreL; - private Drawable mBorderDrawablePreL; + private GradientDrawable mStateLayerGradient; + private LayerDrawable mBackgroundLayerDrawable; /** * @param view The {@link View} on which background will be applied. @@ -100,6 +99,26 @@ /** * @param view The {@link View} on which background will be applied. * @param backgroundColorResId The resource id of the background color. + * @param stateLayerColorResId The resource id of the state layer color. + * @param rippleColorResId The resource id of the ripple color. + * @param cornerRadius The corner radius in pixels of the background drawable. + * @param borderColorResId The resource id of the border color. + * @param borderSizeDimenId The resource id of the border size. + * @param verticalInset The vertical inset of the background drawable. + */ + public RippleBackgroundHelper(View view, @ColorRes int backgroundColorResId, + @ColorRes int stateLayerColorResId, @ColorRes int rippleColorResId, + @Px int cornerRadius, @ColorRes int borderColorResId, @DimenRes int borderSizeDimenId, + @Px int verticalInset) { + this(view, backgroundColorResId, rippleColorResId, cornerRadius, borderColorResId, + borderSizeDimenId, verticalInset); + setStateLayerColor( + AppCompatResources.getColorStateList(view.getContext(), stateLayerColorResId)); + } + + /** + * @param view The {@link View} on which background will be applied. + * @param backgroundColorResId The resource id of the background color. * @param rippleColorResId The resource id of the ripple color. * @param cornerRadii An array of length >= 8 containing 4 pairs of X and Y radius for each * corner, specified in pixels. The corners are ordered top-left, top-right, @@ -112,11 +131,6 @@ @ColorRes int rippleColorResId, float[] cornerRadii, @ColorRes int borderColorResId, @DimenRes int borderSizeDimenId, @Px int verticalInset) { mView = view; - - int paddingStart = ViewCompat.getPaddingStart(mView); - int paddingTop = mView.getPaddingTop(); - int paddingEnd = ViewCompat.getPaddingEnd(mView); - int paddingBottom = mView.getPaddingBottom(); mView.setBackground(createBackgroundDrawable( AppCompatResources.getColorStateList(view.getContext(), rippleColorResId), AppCompatResources.getColorStateList(view.getContext(), borderColorResId), @@ -141,6 +155,11 @@ mBackgroundGradient = new GradientDrawable(); mBackgroundGradient.setCornerRadii(cornerRadii); if (borderSize > 0) mBackgroundGradient.setStroke(borderSize, borderColorList); + mStateLayerGradient = new GradientDrawable(); + mStateLayerGradient.setCornerRadii(cornerRadii); + mStateLayerGradient.setStroke(borderSize, Color.TRANSPARENT); + mBackgroundLayerDrawable = + new LayerDrawable(new Drawable[] {mBackgroundGradient, mStateLayerGradient}); GradientDrawable mask = new GradientDrawable(); mask.setCornerRadii(cornerRadii); mask.setColor(Color.WHITE); @@ -149,7 +168,7 @@ // otherwise it creates corner artifacts on Android S. // Refer to crbug.com/1233720 for details. return new RippleDrawable(convertToRippleDrawableColorList(rippleColorList), - wrapDrawableWithInsets(mBackgroundGradient, verticalInset), mask); + wrapDrawableWithInsets(mBackgroundLayerDrawable, verticalInset), mask); } /** @@ -188,10 +207,31 @@ if (color == mBackgroundColorList) return; mBackgroundColorList = color; + // This works around an issue before Android O where the drawable is drawn in the wrong + // default state. + if (VERSION.SDK_INT < VERSION_CODES.O) { + mBackgroundLayerDrawable.setDrawable(/* index */ 0, mBackgroundGradient); + } mBackgroundGradient.setColor(color); } /** + * Set the color state list that will be used to overlay the background based on the state. + * @param color The {@link ColorStateList}. + */ + void setStateLayerColor(ColorStateList color) { + if (color == mStateLayerColorList) return; + + mStateLayerColorList = color; + // This works around an issue before Android O where the drawable is drawn in the wrong + // default state. + if (VERSION.SDK_INT < VERSION_CODES.O) { + mBackgroundLayerDrawable.setDrawable(/* index */ 1, mStateLayerGradient); + } + mStateLayerGradient.setColor(color); + } + + /** * @param color a single color to be set as the background color on the background drawable. */ public void setBackgroundColor(@ColorInt int color) {
diff --git a/ui/base/interaction/element_identifier.h b/ui/base/interaction/element_identifier.h index 27dfca6..3542cd458 100644 --- a/ui/base/interaction/element_identifier.h +++ b/ui/base/interaction/element_identifier.h
@@ -287,9 +287,18 @@ // text of the name generated is unique, though that makes the exact text // harder to predict. -#define LOCAL_ELEMENT_IDENTIFIER_NAME(File, Line, Name) \ +// This helper macro is required because of how __LINE__ is handled when passed +// between macros, you need an intermediate macro in order to stringify it. +// DO NOT CALL DIRECTLY; used by DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(). +#define LOCAL_ELEMENT_IDENTIFIER_NAME_HELPER(File, Line, Name) \ File "::" #Line "::" #Name +// Intermediate macro required to stringify __LINE__; see +// LOCAL_ELEMENT_IDENTIFIER_NAME_HELPER(). +// DO NOT CALL DIRECTLY; used by DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(). +#define LOCAL_ELEMENT_IDENTIFIER_NAME(File, Line, Name) \ + LOCAL_ELEMENT_IDENTIFIER_NAME_HELPER(File, Line, Name) + // Use this code to declare a local identifier in a function body. #define DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(IdentifierName) \ static constexpr ui::internal::ElementIdentifierImpl \
diff --git a/ui/base/interaction/element_test_util.cc b/ui/base/interaction/element_test_util.cc index 2670056..2c23a9a0 100644 --- a/ui/base/interaction/element_test_util.cc +++ b/ui/base/interaction/element_test_util.cc
@@ -5,6 +5,7 @@ #include "ui/base/interaction/element_test_util.h" #include "base/test/bind.h" +#include "ui/base/interaction/element_tracker.h" namespace ui { @@ -44,6 +45,11 @@ ElementTracker::GetFrameworkDelegate()->NotifyElementHidden(this); } +void TestElementBase::SendCustomEvent(CustomElementEventType event_type) { + DCHECK(visible_); + ElementTracker::GetFrameworkDelegate()->NotifyCustomEvent(this, event_type); +} + // static TrackedElement::FrameworkIdentifier TestElement::GetFrameworkIdentifier() { return kTestFrameworkIdentifier;
diff --git a/ui/base/interaction/element_test_util.h b/ui/base/interaction/element_test_util.h index 389d6057..7a2396f 100644 --- a/ui/base/interaction/element_test_util.h +++ b/ui/base/interaction/element_test_util.h
@@ -26,6 +26,9 @@ // Simulate the element hidden event. void Hide(); + // Simuate a custom event on this element. + void SendCustomEvent(CustomElementEventType event_type); + private: bool visible_ = false; };
diff --git a/ui/base/interaction/element_tracker.cc b/ui/base/interaction/element_tracker.cc index 337c9c2..4c0e8a1 100644 --- a/ui/base/interaction/element_tracker.cc +++ b/ui/base/interaction/element_tracker.cc
@@ -12,6 +12,7 @@ #include "base/auto_reset.h" #include "base/bind.h" #include "base/containers/contains.h" +#include "base/dcheck_is_on.h" #include "base/memory/raw_ptr.h" #include "base/no_destructor.h" #include "ui/base/interaction/element_identifier.h" @@ -32,6 +33,7 @@ shown_callbacks_.set_removal_callback(removal_callback); activated_callbacks_.set_removal_callback(removal_callback); hidden_callbacks_.set_removal_callback(removal_callback); + custom_event_callbacks_.set_removal_callback(removal_callback); } ~ElementData() = default; @@ -44,7 +46,8 @@ bool empty() const { return elements_.empty() && shown_callbacks_.empty() && - activated_callbacks_.empty() && hidden_callbacks_.empty(); + activated_callbacks_.empty() && hidden_callbacks_.empty() && + custom_event_callbacks_.empty(); } size_t num_elements() const { @@ -66,6 +69,10 @@ return hidden_callbacks_.Add(callback); } + Subscription AddCustomEventCallback(Callback callback) { + return custom_event_callbacks_.Add(callback); + } + void NotifyElementShown(TrackedElement* element) { DCHECK_EQ(identifier(), element->identifier()); DCHECK_EQ(static_cast<intptr_t>(context()), @@ -89,6 +96,10 @@ hidden_callbacks_.Notify(element); } + void NotifyCustomEvent(TrackedElement* element) { + custom_event_callbacks_.Notify(element); + } + private: const ElementIdentifier identifier_; const ElementContext context_; @@ -107,6 +118,7 @@ base::RepeatingCallbackList<void(TrackedElement*)> shown_callbacks_; base::RepeatingCallbackList<void(TrackedElement*)> activated_callbacks_; base::RepeatingCallbackList<void(TrackedElement*)> hidden_callbacks_; + base::RepeatingCallbackList<void(TrackedElement*)> custom_event_callbacks_; }; // Ensures that ElementData objects get cleaned up, but only after all callbacks @@ -254,14 +266,27 @@ return GetOrAddElementData(id, context)->AddElementHiddenCallback(callback); } +ElementTracker::Subscription ElementTracker::AddCustomEventCallback( + CustomElementEventType event_type, + ElementContext context, + Callback callback) { + DCHECK(event_type); + DCHECK(context); + // Because custom event callbacks are indexed by event type (and because we + // use the same underlying type for both element ids and custom events), we + // can store both in the same lookup table. + return GetOrAddElementData(event_type, context) + ->AddCustomEventCallback(callback); +} + ElementTracker::ElementTracker() : gc_(std::make_unique<GarbageCollector>(this)) {} -ElementTracker::~ElementTracker() { - NOTREACHED(); -} +ElementTracker::~ElementTracker() = default; void ElementTracker::NotifyElementShown(TrackedElement* element) { + // Prevent garbage collection of dead entries until after we send + // notifications and all callbacks happen. GarbageCollector::Frame gc_frame(gc_.get()); ElementData* const element_data = GetOrAddElementData(element->identifier(), element->context()); @@ -270,6 +295,8 @@ } void ElementTracker::NotifyElementActivated(TrackedElement* element) { + // Prevent garbage collection of dead entries until after we send + // notifications and all callbacks happen. GarbageCollector::Frame gc_frame(gc_.get()); const auto it = element_data_.find(LookupKey(element->identifier(), element->context())); @@ -278,6 +305,8 @@ } void ElementTracker::NotifyElementHidden(TrackedElement* element) { + // Prevent garbage collection of dead entries until after we send + // notifications and all callbacks happen. GarbageCollector::Frame gc_frame(gc_.get()); const auto it = element_data_.find(LookupKey(element->identifier(), element->context())); @@ -287,6 +316,29 @@ gc_frame.Add(data); } +void ElementTracker::NotifyCustomEvent(TrackedElement* element, + CustomElementEventType event_type) { + // Prevent garbage collection of dead entries until after we send + // notifications and all callbacks happen. + GarbageCollector::Frame gc_frame(gc_.get()); + + // We'd like to verify that this element is valid, but don't need to expend + // the effort on an extra lookup if we're not doing checks. +#if DCHECK_IS_ON() + const auto entry = + element_data_.find(LookupKey(element->identifier(), element->context())); + DCHECK(entry != element_data_.end() && entry->second.HasElement(element)); +#endif + + // Since event types are identifiers, we store callbacks by event type rather + // than element identifier. + const auto it = element_data_.find(LookupKey(event_type, element->context())); + // If we don't find a match, that's fine; it means nobody was listening for + // that event type. + if (it != element_data_.end()) + it->second.NotifyCustomEvent(element); +} + ElementTracker::ElementData* ElementTracker::GetOrAddElementData( ElementIdentifier id, ElementContext context) {
diff --git a/ui/base/interaction/element_tracker.h b/ui/base/interaction/element_tracker.h index 72c90bfd..8331db72 100644 --- a/ui/base/interaction/element_tracker.h +++ b/ui/base/interaction/element_tracker.h
@@ -21,6 +21,17 @@ namespace ui { +// Represents a unique type of event, you may create these as needed using the +// DECLARE_CUSTOM_ELEMENT_EVENT_TYPE() and DEFINE_CUSTOM_ELEMENT_EVENT_TYPE() +// macros (see definitions at the bottom of this file). +// +// For testing purposes, if you need a local event type guaranteed to avoid +// global name collisions, use DEFINE_LOCAL_ELEMENT_EVENT_TYPE() instead. +// +// Currently, custom event types are imlpemented using ElementIdentifier, since +// both have the same API requirements. +using CustomElementEventType = ElementIdentifier; + // Represents a visible UI element in a platform-agnostic manner. // // A pointer to this object may be stored after the element becomes visible, but @@ -65,6 +76,8 @@ virtual void NotifyElementShown(TrackedElement* element) = 0; virtual void NotifyElementActivated(TrackedElement* element) = 0; virtual void NotifyElementHidden(TrackedElement* element) = 0; + virtual void NotifyCustomEvent(TrackedElement* element, + CustomElementEventType event_type) = 0; }; // Tracks elements as they become visible, are activated by the user, and @@ -145,6 +158,12 @@ ElementContext context, Callback callback); + // Adds a callback that will be called whenever an event of `event_type` is + // generated within `context` by any element. + Subscription AddCustomEventCallback(CustomElementEventType event_type, + ElementContext context, + Callback callback); + private: friend class base::NoDestructor<ElementTracker>; class ElementData; @@ -161,6 +180,8 @@ void NotifyElementShown(TrackedElement* element) override; void NotifyElementActivated(TrackedElement* element) override; void NotifyElementHidden(TrackedElement* element) override; + void NotifyCustomEvent(TrackedElement* element, + CustomElementEventType event_type) override; ElementData* GetOrAddElementData(ElementIdentifier id, ElementContext context); @@ -197,4 +218,19 @@ } // namespace ui +// Macros for declaring custom element event types. Put the DECLARE call in +// your public header file and the DEFINE in corresponding .cc file. For local +// values to be used in tests, use DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE() +// defined below instead. +#define DECLARE_CUSTOM_ELEMENT_EVENT_TYPE(EventName) \ + DECLARE_ELEMENT_IDENTIFIER_VALUE(EventName) +#define DEFINE_CUSTOM_ELEMENT_EVENT_TYPE(EventName) \ + DEFINE_ELEMENT_IDENTIFIER_VALUE(EventName) + +// This produces a unique, mangled name that can safely be used in tests +// without having to worry about global name collisions. For production code, +// use DECLARE/DEFINE above instead. +#define DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(EventName) \ + DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(EventName) + #endif // UI_BASE_INTERACTION_ELEMENT_TRACKER_H_
diff --git a/ui/base/interaction/element_tracker_unittest.cc b/ui/base/interaction/element_tracker_unittest.cc index 5971ed7f..f046bd0 100644 --- a/ui/base/interaction/element_tracker_unittest.cc +++ b/ui/base/interaction/element_tracker_unittest.cc
@@ -24,8 +24,8 @@ DECLARE_ELEMENT_IDENTIFIER_VALUE(kElementIdentifier1); DEFINE_ELEMENT_IDENTIFIER_VALUE(kElementIdentifier1); const char* const kElementIdentifier1Name = "kElementIdentifier1"; - DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kElementIdentifier2); +DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kCustomEventType1); const ElementContext kElementContext1(1); const ElementContext kElementContext2(2); @@ -378,25 +378,70 @@ EXPECT_CALL_IN_SCOPE(callback, Run(e1.get()), e1->Hide()); } -TEST(ElementTrackerTest, CleanupAfterElementHidden) { - EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty()); +TEST(ElementTrackerTest, AddCustomEventCallback) { + UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback); + auto subscription = + ElementTracker::GetElementTracker()->AddCustomEventCallback( + kCustomEventType1, kElementContext1, callback.Get()); TestElementPtr e1 = std::make_unique<TestElement>(kElementIdentifier1, kElementContext1); e1->Show(); - EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size()); + EXPECT_CALL_IN_SCOPE( + callback, Run(e1.get()), + ElementTracker::GetFrameworkDelegate()->NotifyCustomEvent( + e1.get(), kCustomEventType1)); +} + +TEST(ElementTrackerTest, MultipleCustomEventCallbacks) { + // We will test that custom events work with multiple event types, including + // in the edge case that the event type is the same as an element identifier + // (this should never happen, but should also never break). + const CustomElementEventType kCustomEventType2 = kElementIdentifier1; + UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback); + UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback2); + auto subscription = + ElementTracker::GetElementTracker()->AddCustomEventCallback( + kCustomEventType1, kElementContext1, callback.Get()); + auto subscription2 = + ElementTracker::GetElementTracker()->AddCustomEventCallback( + kCustomEventType2, kElementContext1, callback2.Get()); + TestElementPtr e1 = + std::make_unique<TestElement>(kElementIdentifier1, kElementContext1); + e1->Show(); + EXPECT_CALL_IN_SCOPE( + callback, Run(e1.get()), + ElementTracker::GetFrameworkDelegate()->NotifyCustomEvent( + e1.get(), kCustomEventType1)); + EXPECT_CALL_IN_SCOPE( + callback2, Run(e1.get()), + ElementTracker::GetFrameworkDelegate()->NotifyCustomEvent( + e1.get(), kCustomEventType2)); +} + +TEST(ElementTrackerTest, CleanupAfterElementHidden) { + // Because tests can run concurrently, we have to create our own tracker to + // avoid other tests messing with the data here. + ElementTracker element_tracker; + EXPECT_TRUE(element_tracker.element_data_.empty()); + TestElementPtr e1 = + std::make_unique<TestElement>(kElementIdentifier1, kElementContext1); + element_tracker.NotifyElementShown(e1.get()); + EXPECT_EQ(1U, element_tracker.element_data_.size()); { UNCALLED_MOCK_CALLBACK(ElementTracker::Callback, callback); - auto subscription = - ElementTracker::GetElementTracker()->AddElementShownCallback( - kElementIdentifier1, kElementContext1, callback.Get()); - EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size()); + auto subscription = element_tracker.AddElementShownCallback( + kElementIdentifier1, kElementContext1, callback.Get()); + EXPECT_EQ(1U, element_tracker.element_data_.size()); } - e1->Hide(); - EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty()); + element_tracker.NotifyElementHidden(e1.get()); + EXPECT_TRUE(element_tracker.element_data_.empty()); } TEST(ElementTrackerTest, CleanupAfterCallbacksRemoved) { - EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty()); + // Because tests can run concurrently, we have to create our own tracker to + // avoid other tests messing with the data here. + ElementTracker element_tracker; + EXPECT_TRUE(element_tracker.element_data_.empty()); TestElementPtr e1 = std::make_unique<TestElement>(kElementIdentifier1, kElementContext1); @@ -405,53 +450,59 @@ { base::MockCallback<ElementTracker::Callback> callback; EXPECT_CALL(callback, Run).Times(testing::AnyNumber()); - auto subscription = - ElementTracker::GetElementTracker()->AddElementShownCallback( - kElementIdentifier1, kElementContext1, callback.Get()); - EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size()); - e1->Show(); - EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size()); - e1->Hide(); - EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size()); + auto subscription = element_tracker.AddElementShownCallback( + kElementIdentifier1, kElementContext1, callback.Get()); + EXPECT_EQ(1U, element_tracker.element_data_.size()); + element_tracker.NotifyElementShown(e1.get()); + EXPECT_EQ(1U, element_tracker.element_data_.size()); + element_tracker.NotifyElementHidden(e1.get()); + EXPECT_EQ(1U, element_tracker.element_data_.size()); } - EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty()); + EXPECT_TRUE(element_tracker.element_data_.empty()); // Add element activated callback. { base::MockCallback<ElementTracker::Callback> callback; EXPECT_CALL(callback, Run).Times(testing::AnyNumber()); - auto subscription = - ElementTracker::GetElementTracker()->AddElementActivatedCallback( - kElementIdentifier1, kElementContext1, callback.Get()); - EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size()); + auto subscription = element_tracker.AddElementActivatedCallback( + kElementIdentifier1, kElementContext1, callback.Get()); + EXPECT_EQ(1U, element_tracker.element_data_.size()); } - EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty()); + EXPECT_TRUE(element_tracker.element_data_.empty()); // Add element hidden callback. { base::MockCallback<ElementTracker::Callback> callback; EXPECT_CALL(callback, Run).Times(testing::AnyNumber()); - auto subscription = - ElementTracker::GetElementTracker()->AddElementHiddenCallback( - kElementIdentifier1, kElementContext1, callback.Get()); - EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size()); + auto subscription = element_tracker.AddElementHiddenCallback( + kElementIdentifier1, kElementContext1, callback.Get()); + EXPECT_EQ(1U, element_tracker.element_data_.size()); } - EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty()); + EXPECT_TRUE(element_tracker.element_data_.empty()); + + // Add custom event callback. + { + base::MockCallback<ElementTracker::Callback> callback; + EXPECT_CALL(callback, Run).Times(testing::AnyNumber()); + auto subscription = element_tracker.AddCustomEventCallback( + kCustomEventType1, kElementContext1, callback.Get()); + EXPECT_EQ(1U, element_tracker.element_data_.size()); + } + EXPECT_TRUE(element_tracker.element_data_.empty()); // Add and remove multiple callbacks. { base::MockCallback<ElementTracker::Callback> callback; EXPECT_CALL(callback, Run).Times(testing::AnyNumber()); - auto sub1 = ElementTracker::GetElementTracker()->AddElementShownCallback( + auto sub1 = element_tracker.AddElementShownCallback( kElementIdentifier1, kElementContext1, callback.Get()); - auto sub2 = - ElementTracker::GetElementTracker()->AddElementActivatedCallback( - kElementIdentifier1, kElementContext1, callback.Get()); - auto sub3 = ElementTracker::GetElementTracker()->AddElementHiddenCallback( + auto sub2 = element_tracker.AddElementActivatedCallback( kElementIdentifier1, kElementContext1, callback.Get()); - EXPECT_EQ(1U, ElementTracker::GetElementTracker()->element_data_.size()); + auto sub3 = element_tracker.AddElementHiddenCallback( + kElementIdentifier1, kElementContext1, callback.Get()); + EXPECT_EQ(1U, element_tracker.element_data_.size()); } - EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty()); + EXPECT_TRUE(element_tracker.element_data_.empty()); } // The following test specific conditions that could trigger a UAF or cause @@ -538,18 +589,21 @@ } TEST(ElementTrackerTest, HideDuringShowCallback) { + // Because we have to test for correct cleanup, we have to use an isolated + // ElementTracker. + ElementTracker element_tracker; TestElement e1(kElementIdentifier1, kElementContext1); ElementTracker::Subscription subscription; auto callback = base::BindLambdaForTesting([&](TrackedElement* element) { subscription = ElementTracker::Subscription(); - e1.Hide(); + element_tracker.NotifyElementHidden(&e1); }); - subscription = ElementTracker::GetElementTracker()->AddElementShownCallback( + subscription = element_tracker.AddElementShownCallback( e1.identifier(), e1.context(), callback); - e1.Show(); + element_tracker.NotifyElementShown(&e1); // Verify that cleanup still happens after all callbacks return. - EXPECT_TRUE(ElementTracker::GetElementTracker()->element_data_.empty()); + EXPECT_TRUE(element_tracker.element_data_.empty()); } TEST(SafeElementReferenceTest, ElementRemainsVisible) {
diff --git a/ui/base/interaction/framework_specific_implementation_unittest.cc b/ui/base/interaction/framework_specific_implementation_unittest.cc index 14536ac..3053f19d 100644 --- a/ui/base/interaction/framework_specific_implementation_unittest.cc +++ b/ui/base/interaction/framework_specific_implementation_unittest.cc
@@ -5,6 +5,7 @@ #include "ui/base/interaction/framework_specific_implementation.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/base/interaction/element_test_util.h" namespace ui {
diff --git a/ui/base/interaction/interaction_sequence.cc b/ui/base/interaction/interaction_sequence.cc index ffb2a24..96881e9 100644 --- a/ui/base/interaction/interaction_sequence.cc +++ b/ui/base/interaction/interaction_sequence.cc
@@ -135,7 +135,10 @@ InteractionSequence::Builder& InteractionSequence::Builder::AddStep( std::unique_ptr<Step> step) { // Do consistency checks and set up defaults. - DCHECK(!step->id == step->uses_named_element()) + const bool is_custom_event_any_element = + step->type == StepType::kCustomEvent && !step->id && + !step->uses_named_element(); + DCHECK(is_custom_event_any_element || !step->id == step->uses_named_element()) << " A step must set an identifier or a name, but not both."; DCHECK(configuration_->steps.empty() || !step->element) << " Only the initial step of a sequence may have a pre-set element."; @@ -145,27 +148,38 @@ // Set reasonable defaults for must_be_visible based on step type and // parameters. if (step->uses_named_element() && step->type != StepType::kHidden) { - DCHECK(!step->must_be_visible.has_value() || step->must_be_visible.value()); + DCHECK(!step->must_be_visible.has_value() || step->must_be_visible.value()) + << "Named elements not being hidden must be visible at step start."; step->must_be_visible = true; + } else if (is_custom_event_any_element) { + DCHECK(!step->must_be_visible.has_value() || !step->must_be_visible.value()) + << "A custom event with no element restrictions cannot specify that" + " its element must start visible, as we will not know which element" + " to refer to."; + step->must_be_visible = false; } else { step->must_be_visible = - step->must_be_visible.value_or(step->type == StepType::kActivated); + step->must_be_visible.value_or(step->type == StepType::kActivated || + step->type == StepType::kCustomEvent); } DCHECK(!step->element || step->must_be_visible.value()) << " Initial step with associated element must be visible from start."; DCHECK(step->type != InteractionSequence::StepType::kHidden || !step->must_remain_visible.has_value() || - !step->must_remain_visible.value()); + !step->must_remain_visible.value()) + << "Hide steps cannot specify that the element should remain visible."; DCHECK(step->type != InteractionSequence::StepType::kShown || !step->uses_named_element() || !step->transition_only_on_event) << " kShown steps with transition_only_on_event are not compatible with" " named elements since a named element ceases to be valid when it" " becomes hidden."; - if (!configuration_->context) + if (!configuration_->context) { configuration_->context = step->context; - else - DCHECK(!step->context || step->context == configuration_->context); + } else { + DCHECK(!step->context || step->context == configuration_->context) + << "Cannot [currently] change context during a sequence."; + } // Since the must_remain_visible value can be dependent on the following // step, we'll set it on the previous step, then set it on the final step @@ -242,8 +256,13 @@ } InteractionSequence::StepBuilder& InteractionSequence::StepBuilder::SetType( - StepType step_type) { + StepType step_type, + CustomElementEventType event_type) { + DCHECK_EQ(step_type == StepType::kCustomEvent, static_cast<bool>(event_type)) + << "Custom events require an event type; event type may not be specified" + " for other step types."; step_->type = step_type; + step_->custom_event_type = event_type; return *this; } @@ -334,10 +353,10 @@ } // If this is called during a step transition, we may want to watch for - // activation of the element for the next step. (If the next step doesn't - // refer to the element we just named, it will already have a subscription - // and this call will be a no-op). - MaybeWatchForActivationDuringStepTransition(); + // activation or event on the element for the next step. (If the next step + // doesn't refer to the element we just named, it will already have a + // subscription and this call will be a no-op). + MaybeWatchForTriggerDuringStepTransition(); } TrackedElement* InteractionSequence::GetNamedElement( @@ -373,6 +392,14 @@ DoStepTransition(element); } +void InteractionSequence::OnCustomEvent(TrackedElement* element) { + DCHECK_EQ(StepType::kCustomEvent, next_step()->type); + if (next_step()->id && next_step()->id != element->identifier()) + return; + if (MatchesNameIfSpecified(element, next_step()->element_name)) + DoStepTransition(element); +} + void InteractionSequence::OnElementHidden(TrackedElement* element) { if (!started_) { DCHECK_EQ(next_step()->element, element); @@ -386,7 +413,7 @@ // If the current step is marked as needing to remain visible and we haven't // seen the triggering event for the next step, abort. if (current_step_->must_remain_visible.value() && - !activated_during_callback_) { + !trigger_during_callback_) { Abort(AbortedReason::kElementHiddenDuringStep); return; } @@ -411,22 +438,46 @@ } } -void InteractionSequence::OnElementActivatedDuringStepTransition( +void InteractionSequence::OnTriggerDuringStepTransition( TrackedElement* element) { if (!next_step()) return; - DCHECK(element->identifier() == next_step()->id); - DCHECK(MatchesNameIfSpecified(element, next_step()->element_name)); + switch (next_step()->type) { + case StepType::kActivated: + // We should know the identifier and name ahead of time for activation + // steps, so just make sure nothing has gone awry. + DCHECK(element->identifier() == next_step()->id); + DCHECK(MatchesNameIfSpecified(element, next_step()->element_name)); + break; + case StepType::kCustomEvent: + // Since we don't specify the element ID when registering for custom + // events we have to see if we specified an ID or name and if so, whether + // it matches the element we actually got. + if (next_step()->id && element->identifier() != next_step()->id) + return; + if (!MatchesNameIfSpecified(element, next_step()->element_name)) + return; + break; + default: + NOTREACHED(); + return; + } + + // Barring disaster, we will immediately transition as soon as we finish + // processing the current step. next_step()->element = element; + trigger_during_callback_ = true; + + // Since we've hit the trigger for the next step, we need to make sure we + // clean up (and possibly abort) if the element goes away before we can + // finish processing the current step. next_step()->subscription = ElementTracker::GetElementTracker()->AddElementHiddenCallback( - next_step()->id, context(), + element->identifier(), context(), base::BindRepeating( &InteractionSequence::OnElementHiddenDuringStepTransition, base::Unretained(this))); - - activated_during_callback_ = true; } void InteractionSequence::OnElementHiddenDuringStepTransition( @@ -450,22 +501,36 @@ } } -void InteractionSequence::MaybeWatchForActivationDuringStepTransition() { - // This code only runs if we're in the middle of processing a step, there is - // a next step of type kActivated, the step has a valid ID (which it may not - // have if we haven't yet named the element for the next step) and we haven't - // already added the temporary callback. - if (!processing_step_ || configuration_->steps.empty() || !next_step()->id || - next_step()->type != StepType::kActivated || next_step()->subscription) { +void InteractionSequence::MaybeWatchForTriggerDuringStepTransition() { + // This should only be called while we're processing a step, there is a next + // step we care about, and we aren't already subscribed for an event on that + // step. + if (!processing_step_ || configuration_->steps.empty() || + next_step()->subscription) { return; } - next_step()->subscription = - ElementTracker::GetElementTracker()->AddElementActivatedCallback( - next_step()->id, context(), - base::BindRepeating( - &InteractionSequence::OnElementActivatedDuringStepTransition, - base::Unretained((this)))); + if (next_step()->type == StepType::kActivated && next_step()->id) { + // If the next step is an activation step and we already know the ID (i.e. + // it's either not a named element or the element in question has been + // named) then add the appropriate temporary callback. + next_step()->subscription = + ElementTracker::GetElementTracker()->AddElementActivatedCallback( + next_step()->id, context(), + base::BindRepeating( + &InteractionSequence::OnTriggerDuringStepTransition, + base::Unretained((this)))); + } else if (next_step()->type == StepType::kCustomEvent) { + // If the next step is a custom event, we might not yet know the name or ID + // of the element, but we can still listen for the custom event type. We'll + // filter out irrelevant elements in the callback itself. + next_step()->subscription = + ElementTracker::GetElementTracker()->AddCustomEventCallback( + next_step()->custom_event_type, context(), + base::BindRepeating( + &InteractionSequence::OnTriggerDuringStepTransition, + base::Unretained((this)))); + } } void InteractionSequence::DoStepTransition(TrackedElement* element) { @@ -500,7 +565,7 @@ current_step_->type == StepType::kHidden ? nullptr : element; if (current_step_->element) { current_step_->subscription = tracker->AddElementHiddenCallback( - current_step_->id, context(), + current_step_->element->identifier(), context(), base::BindRepeating(&InteractionSequence::OnElementHidden, base::Unretained(this))); } else { @@ -517,11 +582,11 @@ // requires the element to be visible and it is not), then the appropriate // transition (or Abort()) will happen in StageNextStep() below. // - // If, however, the callback *activates* the next target element, and the - // next element is of type kActivated, then the activation will not - // register unless we explicitly listen for it. This will add a temporary - // callback in the case where - MaybeWatchForActivationDuringStepTransition(); + // If, however, the callback *activates* or sends a custom event on the next + // target element, and the next step is of the matching type, then the event + // will not register unless we explicitly listen for it. This will add a + // temporary callback to handle this case. + MaybeWatchForTriggerDuringStepTransition(); // Start the step. Like all callbacks, this could abort the sequence, or // cause `element` to become invalid. Because of this we use the element @@ -561,12 +626,13 @@ auto* const tracker = ElementTracker::GetElementTracker(); Step* const next = next_step(); - DCHECK(!activated_during_callback_ || next->type == StepType::kActivated); + DCHECK(!trigger_during_callback_ || next->type == StepType::kActivated || + next->type == StepType::kCustomEvent); // Note that if the target element for the next step was activated and then // hidden during the previous step transition, `next_element` could be null. TrackedElement* next_element; - if (activated_during_callback_ || next->element) { + if (trigger_during_callback_ || next->element) { next_element = next->element; } else if (next->uses_named_element()) { next->element = GetNamedElement(next->element_name); @@ -579,7 +645,7 @@ next_element = tracker->GetFirstMatchingElement(next->id, context()); } - if (!activated_during_callback_ && next->must_be_visible.value() && + if (!trigger_during_callback_ && next->must_be_visible.value() && !next_element) { // We're going to abort, but we have to finish the current step first. if (current_step_) { @@ -621,8 +687,8 @@ } break; case StepType::kActivated: - if (activated_during_callback_) { - activated_during_callback_ = false; + if (trigger_during_callback_) { + trigger_during_callback_ = false; DoStepTransition(next_element); } else { DCHECK(next_element || !next->uses_named_element()); @@ -642,6 +708,29 @@ } } break; + case StepType::kCustomEvent: + if (trigger_during_callback_) { + trigger_during_callback_ = false; + DoStepTransition(next_element); + } else { + DCHECK(next_element || !next->uses_named_element()); + next->subscription = tracker->AddCustomEventCallback( + next->custom_event_type, context(), + base::BindRepeating(&InteractionSequence::OnCustomEvent, + base::Unretained(this))); + // It's possible to have the element hidden between the time we stage + // the event and when the custom event would actually come in (which + // could be never). In this case, we should abort. + if (next_step()->must_be_visible.value()) { + DCHECK(next->id); + next_step_hidden_subscription_ = tracker->AddElementHiddenCallback( + next->id, context(), + base::BindRepeating( + &InteractionSequence::OnElementHiddenWaitingForActivate, + base::Unretained(this))); + } + } + break; } }
diff --git a/ui/base/interaction/interaction_sequence.h b/ui/base/interaction/interaction_sequence.h index 7fc7be6..c701a70 100644 --- a/ui/base/interaction/interaction_sequence.h +++ b/ui/base/interaction/interaction_sequence.h
@@ -70,7 +70,11 @@ kActivated, // Represents an element with the specified ID becoming hidden or // destroyed, or no elements with the specified ID being visible. - kHidden + kHidden, + // Represents a custom event with a specific custom event type. You may + // further specify a required element name or ID to filter down which + // events you actually want to step on vs. ignore. + kCustomEvent }; // Details why a sequence was aborted. @@ -120,6 +124,7 @@ StepType type = StepType::kShown; ElementIdentifier id; + CustomElementEventType custom_event_type; std::string element_name; ElementContext context; @@ -185,11 +190,12 @@ void operator=(StepBuilder& other) = delete; // Sets the unique identifier for this step. Either this or - // SetElementName() is required. + // SetElementName() is required for all step types except kCustomEvent. StepBuilder& SetElementID(ElementIdentifier element_id); // Sets the step to refer to a named element instead of an - // ElementIdentifier. Either this or SetElementID() is required. + // ElementIdentifier. Either this or SetElementID() is required for all + // step types other than kCustomEvent. StepBuilder& SetElementName(const base::StringPiece& name); // Sets the context for the element; useful for setting up the initial @@ -197,8 +203,11 @@ // Prefer to use Builder::SetContext() if possible. StepBuilder& SetContext(ElementContext context); - // Sets the type of step. Required. - StepBuilder& SetType(StepType step_type); + // Sets the type of step. Required. You must set `event_type` if and only + // if `step_type` is kCustomEvent. + StepBuilder& SetType( + StepType step_type, + CustomElementEventType event_type = CustomElementEventType()); // Indicates that the specified element must be visible at the start of the // step. Defaults to true for StepType::kActivated, false otherwise. Failure @@ -303,16 +312,17 @@ void OnElementShown(TrackedElement* element); void OnElementActivated(TrackedElement* element); void OnElementHidden(TrackedElement* element); + void OnCustomEvent(TrackedElement* element); // Callbacks used only during step transitions to cache certain events. - void OnElementActivatedDuringStepTransition(TrackedElement* element); + void OnTriggerDuringStepTransition(TrackedElement* element); void OnElementHiddenDuringStepTransition(TrackedElement* element); void OnElementHiddenWaitingForActivate(TrackedElement* element); // While we're transitioning steps, it's possible for an activation that // would trigger the following step to come in. This method adds a callback // that's valid only during the step transition to watch for this event. - void MaybeWatchForActivationDuringStepTransition(); + void MaybeWatchForTriggerDuringStepTransition(); // A note on the next three methods - DoStepTransition(), StageNextStep(), and // Abort(): To prevent re-entrancy issues, they must always be the final call @@ -352,7 +362,7 @@ bool missing_first_element_ = false; bool started_ = false; - bool activated_during_callback_ = false; + bool trigger_during_callback_ = false; bool processing_step_ = false; std::unique_ptr<Step> current_step_; ElementTracker::Subscription next_step_hidden_subscription_;
diff --git a/ui/base/interaction/interaction_sequence_unittest.cc b/ui/base/interaction/interaction_sequence_unittest.cc index 5290166..d1b70860 100644 --- a/ui/base/interaction/interaction_sequence_unittest.cc +++ b/ui/base/interaction/interaction_sequence_unittest.cc
@@ -29,6 +29,8 @@ DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestIdentifier1); DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestIdentifier2); DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestIdentifier3); +DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kCustomEventType1); +DEFINE_LOCAL_CUSTOM_ELEMENT_EVENT_TYPE(kCustomEventType2); const ElementContext kTestContext1(1); const ElementContext kTestContext2(2); @@ -238,6 +240,157 @@ element.Activate(); } +TEST(InteractionSeuenceTest, TransitionOnCustomEventSameId) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step); + TestElement element(kTestIdentifier1, kTestContext1); + element.Show(); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetStartCallback(step.Get()) + .Build()) + .Build(); + sequence->Start(); + EXPECT_CALLS_IN_SCOPE_2(step, Run(sequence.get(), &element), completed, Run, + element.SendCustomEvent(kCustomEventType1)); +} + +TEST(InteractionSeuenceTest, TransitionOnCustomEventDifferentId) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step); + TestElement element(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element.Show(); + element2.Show(); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetStartCallback(step.Get()) + .Build()) + .Build(); + sequence->Start(); + // Non-matching ID should not trigger the step, even if the event type + // matches. + element.SendCustomEvent(kCustomEventType1); + EXPECT_CALLS_IN_SCOPE_2(step, Run(sequence.get(), &element2), completed, Run, + element2.SendCustomEvent(kCustomEventType1)); +} + +TEST(InteractionSeuenceTest, TransitionOnCustomEventAnyElement) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step2); + TestElement element(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element.Show(); + element2.Show(); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element)) + .AddStep(InteractionSequence::StepBuilder() + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetStartCallback(step.Get()) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetStartCallback(step2.Get()) + .Build()) + .Build(); + sequence->Start(); + EXPECT_CALL_IN_SCOPE(step, Run(sequence.get(), &element), + element.SendCustomEvent(kCustomEventType1)); + EXPECT_CALLS_IN_SCOPE_2(step2, Run(sequence.get(), &element2), completed, Run, + element2.SendCustomEvent(kCustomEventType1)); +} + +TEST(InteractionSeuenceTest, TransitionOnCustomEventMultipleEvents) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step2); + TestElement element(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element.Show(); + element2.Show(); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element)) + .AddStep(InteractionSequence::StepBuilder() + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetStartCallback(step.Get()) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType2) + .SetStartCallback(step2.Get()) + .Build()) + .Build(); + sequence->Start(); + + // This is the wrong event type so won't cause a transition. + element.SendCustomEvent(kCustomEventType2); + + EXPECT_CALL_IN_SCOPE(step, Run(sequence.get(), &element), + element.SendCustomEvent(kCustomEventType1)); + + // This is the wrong event type so won't cause a transition. + element2.SendCustomEvent(kCustomEventType1); + + EXPECT_CALLS_IN_SCOPE_2(step2, Run(sequence.get(), &element2), completed, Run, + element2.SendCustomEvent(kCustomEventType2)); +} + +TEST(InteractionSeuenceTest, TransitionOnCustomEventFailsIfMustBeVisible) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step); + TestElement element(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element.Show(); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetMustBeVisibleAtStart(true) + .SetStartCallback(step.Get()) + .Build()) + .Build(); + EXPECT_CALL_IN_SCOPE( + aborted, + Run(nullptr, element2.identifier(), + InteractionSequence::StepType::kCustomEvent, + InteractionSequence::AbortedReason::kElementNotVisibleAtStartOfStep), + sequence->Start()); +} + TEST(InteractionSequenceTest, TransitionOnElementShown) { UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); @@ -436,7 +589,28 @@ EXPECT_CALL_IN_SCOPE(aborted, Run, element2.Hide()); } -TEST(InteractionSequenceTest, NoWithInitialElementTransitionsOnActivation) { +TEST(InteractionSequenceTest, + FailIfFirstElementBecomesHiddenBeforeCustomEvent) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + element1.Show(); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element1.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + sequence->Start(); + EXPECT_CALL_IN_SCOPE(aborted, Run, element1.Hide()); +} + +TEST(InteractionSequenceTest, NoInitialElementTransitionsOnActivation) { UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step); @@ -460,7 +634,29 @@ element.Activate(); } -TEST(InteractionSequenceTest, NoWithInitialElementTransitionsOnShown) { +TEST(InteractionSequenceTest, NoInitialElementTransitionsOnCustomEvent) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step); + TestElement element(kTestIdentifier1, kTestContext1); + element.Show(); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .SetContext(element.context()) + .AddStep(InteractionSequence::StepBuilder() + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetStartCallback(step.Get()) + .Build()) + .Build(); + sequence->Start(); + EXPECT_CALLS_IN_SCOPE_2(step, Run(sequence.get(), &element), completed, Run, + element.SendCustomEvent(kCustomEventType1)); +} + +TEST(InteractionSequenceTest, NoInitialElementTransitionsOnShown) { UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step); @@ -968,6 +1164,81 @@ element2.Show()); } +TEST(InteractionSequenceTest, CustomEventDuringCallbackDifferentView) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepEndCallback, step1_end); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step2_start); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + + auto callback = [&](InteractionSequence*, TrackedElement*) { + element2.SendCustomEvent(kCustomEventType1); + }; + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element1.identifier()) + .SetType(InteractionSequence::StepType::kActivated) + .SetStartCallback( + base::BindLambdaForTesting(std::move(callback))) + .SetEndCallback(step1_end.Get()) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetStartCallback(step2_start.Get()) + .Build()) + .Build(); + + sequence->Start(); + EXPECT_CALLS_IN_SCOPE_3(step1_end, Run, step2_start, Run, completed, Run, + element1.Activate()); +} + +TEST(InteractionSequenceTest, CustomEventDuringCallbackSameView) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepEndCallback, step1_end); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step2_start); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element1.Show(); + + auto callback = [&](InteractionSequence*, TrackedElement*) { + element2.SendCustomEvent(kCustomEventType1); + }; + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kShown) + .SetStartCallback( + base::BindLambdaForTesting(std::move(callback))) + .SetEndCallback(step1_end.Get()) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetStartCallback(step2_start.Get()) + .Build()) + .Build(); + + sequence->Start(); + EXPECT_CALLS_IN_SCOPE_3(step1_end, Run, step2_start, Run, completed, Run, + element2.Show()); +} + TEST(InteractionSequenceTest, HideAfterActivateDoesntAbort) { UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); @@ -1006,6 +1277,83 @@ EXPECT_CALL_IN_SCOPE(completed, Run, element2.Show()); } +TEST(InteractionSequenceTest, HideAfterCustomEventDoesntAbort) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier3, kTestContext1); + element1.Show(); + element3.Show(); + + auto callback = [&](InteractionSequence*, TrackedElement*) { + element2.SendCustomEvent(kCustomEventType1); + element2.Hide(); + }; + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kShown) + .SetStartCallback( + base::BindLambdaForTesting(std::move(callback))) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element3.identifier()) + .SetType(InteractionSequence::StepType::kShown) + .Build()) + .Build(); + + sequence->Start(); + EXPECT_CALL_IN_SCOPE(completed, Run, element2.Show()); +} + +TEST(InteractionSequenceTest, HideUnnamedElementAfterCustomEventDoesntAbort) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier3, kTestContext1); + element1.Show(); + element3.Show(); + + auto callback = [&](InteractionSequence*, TrackedElement*) { + element2.SendCustomEvent(kCustomEventType1); + element2.Hide(); + }; + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kShown) + .SetStartCallback( + base::BindLambdaForTesting(std::move(callback))) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element3.identifier()) + .SetType(InteractionSequence::StepType::kShown) + .Build()) + .Build(); + + sequence->Start(); + EXPECT_CALL_IN_SCOPE(completed, Run, element2.Show()); +} + TEST(InteractionSequenceTest, HideDuringStepStartedCallbackAborts) { UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); @@ -1070,6 +1418,74 @@ EXPECT_CALL_IN_SCOPE(aborted, Run, sequence->Start()); } +TEST(InteractionSequenceTest, + HideDuringStepStartedCallbackBeforeCustomEventAborts) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element1.Show(); + + auto callback = [&](InteractionSequence*, TrackedElement*) { + element2.Hide(); + }; + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kShown) + .SetStartCallback( + base::BindLambdaForTesting(std::move(callback))) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + + sequence->Start(); + EXPECT_CALL_IN_SCOPE(aborted, Run, element2.Show()); +} + +TEST(InteractionSequenceTest, + HideDuringStepEndedCallbackBeforeCustomEventAborts) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepStartCallback, step2_start); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepEndCallback, step2_end); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element1.Show(); + + auto callback = [&](TrackedElement*) { element2.Hide(); }; + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement( + &element1, InteractionSequence::StepStartCallback(), + base::BindLambdaForTesting(std::move(callback)))) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kShown) + .SetMustBeVisibleAtStart(true) + .SetStartCallback(step2_start.Get()) + .SetEndCallback(step2_end.Get()) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + + EXPECT_CALL_IN_SCOPE(aborted, Run, sequence->Start()); +} + TEST(InteractionSequenceTest, ElementHiddenDuringFinalStepStart) { UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); @@ -1439,6 +1855,272 @@ EXPECT_FALSE(sequence); } +// Bait-and-switch tests - verify that when an element must start visible and +// there are multiple such elements, it's okay if any of them receive the +// following event. + +TEST(InteractionSequenceTest, BaitAndSwitchActivation) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + + std::unique_ptr<InteractionSequence> sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kActivated) + .SetMustBeVisibleAtStart(true) + .Build()) + .Build(); + + sequence->Start(); + element3.Show(); + element2.Hide(); + EXPECT_CALL_IN_SCOPE(completed, Run, element3.Activate()); +} + +TEST(InteractionSequenceTest, BaitAndSwitchActivationFails) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + + std::unique_ptr<InteractionSequence> sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kActivated) + .SetMustBeVisibleAtStart(true) + .Build()) + .Build(); + + sequence->Start(); + EXPECT_CALL_IN_SCOPE(aborted, Run, { + // By hiding before showing the other element, there are no visible + // elements. + element2.Hide(); + element3.Show(); + element3.Activate(); + }); +} + +TEST(InteractionSequenceTest, BaitAndSwitchActivationDuringStepTransition) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + + auto step_start = + base::BindLambdaForTesting([&](InteractionSequence*, TrackedElement*) { + element3.Show(); + element2.Hide(); + element3.Activate(); + }); + + std::unique_ptr<InteractionSequence> sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement( + &element1, std::move(step_start))) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kActivated) + .SetMustBeVisibleAtStart(true) + .Build()) + .Build(); + + EXPECT_CALL_IN_SCOPE(completed, Run, sequence->Start()); +} + +TEST(InteractionSequenceTest, + BaitAndSwitchActivationDuringStepTransitionEventuallyConsistent) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + + auto step_start = + base::BindLambdaForTesting([&](InteractionSequence*, TrackedElement*) { + // By hiding before showing the other element, there are no visible + // elements. However, because the system becomes consistent before the + // end of the callback and the event is triggered, we are allowed to + // proceed. This is technically incorrect behavior but adds a bit of + // forgiveness into the system if visibility of elements is updated in + // arbitrary order. + element2.Hide(); + element3.Show(); + element3.Activate(); + }); + + std::unique_ptr<InteractionSequence> sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement( + &element1, std::move(step_start))) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kActivated) + .SetMustBeVisibleAtStart(true) + .Build()) + .Build(); + + EXPECT_CALL_IN_SCOPE(completed, Run, sequence->Start()); +} + +TEST(InteractionSequenceTest, BaitAndSwitchCustomEvent) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + + std::unique_ptr<InteractionSequence> sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetMustBeVisibleAtStart(true) + .Build()) + .Build(); + + sequence->Start(); + element3.Show(); + element2.Hide(); + EXPECT_CALL_IN_SCOPE(completed, Run, + element3.SendCustomEvent(kCustomEventType1)); +} + +TEST(InteractionSequenceTest, BaitAndSwitchCustomEventFails) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + + std::unique_ptr<InteractionSequence> sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1)) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetMustBeVisibleAtStart(true) + .Build()) + .Build(); + + sequence->Start(); + // By hiding before showing the other element, there are no visible elements. + EXPECT_CALL_IN_SCOPE(aborted, Run, { + element2.Hide(); + element3.Show(); + element3.SendCustomEvent(kCustomEventType1); + }); +} + +TEST(InteractionSequenceTest, BaitAndSwitchCustomEventDuringStepTransition) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + + auto step_start = + base::BindLambdaForTesting([&](InteractionSequence*, TrackedElement*) { + element3.Show(); + element2.Hide(); + element3.SendCustomEvent(kCustomEventType1); + }); + + std::unique_ptr<InteractionSequence> sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement( + &element1, std::move(step_start))) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetMustBeVisibleAtStart(true) + .Build()) + .Build(); + + EXPECT_CALL_IN_SCOPE(completed, Run, sequence->Start()); +} + +TEST(InteractionSequenceTest, + BaitAndSwitchCustomEventDuringStepTransitionEventuallyConsistent) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + + auto step_start = + base::BindLambdaForTesting([&](InteractionSequence*, TrackedElement*) { + // By hiding before showing the other element, there are no visible + // elements. However, because the system becomes consistent before the + // end of the callback and the event is triggered, we are allowed to + // proceed. This is technically incorrect behavior but adds a bit of + // forgiveness into the system if visibility of elements is updated in + // arbitrary order. + element2.Hide(); + element3.Show(); + element3.SendCustomEvent(kCustomEventType1); + }); + + std::unique_ptr<InteractionSequence> sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement( + &element1, std::move(step_start))) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .SetMustBeVisibleAtStart(true) + .Build()) + .Build(); + + EXPECT_CALL_IN_SCOPE(completed, Run, sequence->Start()); +} + // Test step default values: TEST(InteractionSequenceTest, MustBeVisibleAtStart_DefaultsToTrueForActivated) { @@ -1480,7 +2162,84 @@ } TEST(InteractionSequenceTest, - MustRemainVisible_DefaultsBasedOnCurrentAndNextStep) { + MustBeVisibleAtStart_DefaultsToTrueForCustomEventIfElementIdSet) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepEndCallback, step1_end); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepEndCallback, step2_end); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier3, kTestContext1); + auto sequence = + InteractionSequence::Builder() + .SetContext(element1.context()) + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element1.identifier()) + .SetType(InteractionSequence::StepType::kShown) + .SetEndCallback(step1_end.Get()) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kHidden) + .SetEndCallback(step2_end.Get()) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element3.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + + sequence->Start(); + EXPECT_CALLS_IN_SCOPE_3( + step1_end, Run, step2_end, Run, aborted, + Run(nullptr, element3.identifier(), + InteractionSequence::StepType::kCustomEvent, + InteractionSequence::AbortedReason::kElementNotVisibleAtStartOfStep), + element1.Show()); +} + +TEST(InteractionSequenceTest, + MustBeVisibleAtStart_DefaultsToFalseForCustomEventWithUnnamedElement) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepEndCallback, step1_end); + UNCALLED_MOCK_CALLBACK(InteractionSequence::StepEndCallback, step2_end); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier3, kTestContext1); + auto sequence = + InteractionSequence::Builder() + .SetContext(element1.context()) + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element1.identifier()) + .SetType(InteractionSequence::StepType::kShown) + .SetEndCallback(step1_end.Get()) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetType(InteractionSequence::StepType::kHidden) + .SetEndCallback(step2_end.Get()) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + + sequence->Start(); + EXPECT_CALL_IN_SCOPE(step1_end, Run, element1.Show()); + element3.Show(); + EXPECT_CALLS_IN_SCOPE_2(step2_end, Run, completed, Run, + element3.SendCustomEvent(kCustomEventType1)); +} + +TEST(InteractionSequenceTest, + MustRemainVisible_DefaultsBasedOnCurrentAndNextStep_Activation) { UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); TestElement element1(kTestIdentifier1, kTestContext1); @@ -1537,6 +2296,66 @@ element3.Hide()); } +TEST(InteractionSequenceTest, + MustRemainVisible_DefaultsBasedOnCurrentAndNextStep_CustomEvents) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + TestElement element3(kTestIdentifier3, kTestContext1); + element1.Show(); + auto sequence = + InteractionSequence::Builder() + .SetContext(element1.context()) + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + // Shown followed by hidden defaults to must_remain_visible = false. + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element1.identifier()) + .SetType(InteractionSequence::StepType::kShown) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element1.identifier()) + .SetType(InteractionSequence::StepType::kHidden) + .Build()) + // Activated step defaults to false. + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element2.identifier()) + .SetMustBeVisibleAtStart(false) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + // Shown followed by activated defaults to true. + // (We will fail the sequence on this step.) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element3.identifier()) + .SetType(InteractionSequence::StepType::kShown) + .Build()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementID(element3.identifier()) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType2) + .Build()) + .Build(); + + sequence->Start(); + // Trigger step 2. + element1.Hide(); + element2.Show(); + // Trigger step 3. + element2.SendCustomEvent(kCustomEventType1); + // Trigger step 4. + element3.Show(); + + // Fail step four. + EXPECT_CALL_IN_SCOPE( + aborted, + Run(&element3, element3.identifier(), + InteractionSequence::StepType::kShown, + InteractionSequence::AbortedReason::kElementHiddenDuringStep), + element3.Hide()); +} + // SetTransitionOnlyOnEvent tests: TEST(InteractionSequenceTest, @@ -2029,6 +2848,192 @@ } TEST(InteractionSequenceTest, + NameElement_CustomEvent_NamedBeforeSequenceStarts) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + element1.Show(); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .SetContext(element1.context()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementName(kElementName1) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + sequence->NameElement(&element1, kElementName1); + sequence->Start(); + EXPECT_CALL_IN_SCOPE(completed, Run, + element1.SendCustomEvent(kCustomEventType1)); +} + +TEST(InteractionSequenceTest, + NameElement_CustomEvent_NamedBeforeSequenceStarts_AbortsIfHidden) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + element1.Show(); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .SetContext(element1.context()) + .AddStep(InteractionSequence::StepBuilder() + .SetElementName(kElementName1) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + sequence->NameElement(&element1, kElementName1); + sequence->Start(); + EXPECT_CALL_IN_SCOPE(aborted, Run, element1.Hide()); +} + +TEST(InteractionSequenceTest, NameElement_CustomEvent_NamedDuringStep) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + auto step = base::BindLambdaForTesting( + [&](InteractionSequence* sequence, TrackedElement* element) { + sequence->NameElement(&element2, kElementName1); + }); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1, + std::move(step))) + .AddStep(InteractionSequence::StepBuilder() + .SetElementName(kElementName1) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + sequence->Start(); + EXPECT_CALL_IN_SCOPE(completed, Run, + element2.SendCustomEvent(kCustomEventType1)); +} + +TEST(InteractionSequenceTest, + NameElement_CustomEvent_NamedDuringStep_AbortsIfHidden) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + auto step = base::BindLambdaForTesting( + [&](InteractionSequence* sequence, TrackedElement* element) { + sequence->NameElement(&element2, kElementName1); + }); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1, + std::move(step))) + .AddStep(InteractionSequence::StepBuilder() + .SetElementName(kElementName1) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + sequence->Start(); + EXPECT_CALL_IN_SCOPE(aborted, Run, element2.Hide()); +} + +TEST(InteractionSequenceTest, + NameElement_CustomEvent_NamedAndActivatedDuringStep) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + auto step = base::BindLambdaForTesting( + [&](InteractionSequence* sequence, TrackedElement* element) { + sequence->NameElement(&element2, kElementName1); + element2.SendCustomEvent(kCustomEventType1); + }); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1, + std::move(step))) + .AddStep(InteractionSequence::StepBuilder() + .SetElementName(kElementName1) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + EXPECT_CALL_IN_SCOPE(completed, Run, sequence->Start()); +} + +TEST(InteractionSequenceTest, + NameElement_CustomEvent_NamedAndHiddenDuringStep_Aborts) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + auto step = base::BindLambdaForTesting( + [&](InteractionSequence* sequence, TrackedElement* element) { + sequence->NameElement(&element2, kElementName1); + element2.Hide(); + }); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1, + std::move(step))) + .AddStep(InteractionSequence::StepBuilder() + .SetElementName(kElementName1) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + EXPECT_CALL_IN_SCOPE(aborted, Run, sequence->Start()); +} + +TEST(InteractionSequenceTest, + NameElement_CustomEvent_NamedActivatedAndHiddenDuringStep) { + UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); + UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed); + TestElement element1(kTestIdentifier1, kTestContext1); + TestElement element2(kTestIdentifier2, kTestContext1); + element1.Show(); + element2.Show(); + auto step = base::BindLambdaForTesting( + [&](InteractionSequence* sequence, TrackedElement* element) { + sequence->NameElement(&element2, kElementName1); + element2.SendCustomEvent(kCustomEventType1); + element2.Hide(); + }); + auto sequence = + InteractionSequence::Builder() + .SetAbortedCallback(aborted.Get()) + .SetCompletedCallback(completed.Get()) + .AddStep(InteractionSequence::WithInitialElement(&element1, + std::move(step))) + .AddStep(InteractionSequence::StepBuilder() + .SetElementName(kElementName1) + .SetType(InteractionSequence::StepType::kCustomEvent, + kCustomEventType1) + .Build()) + .Build(); + EXPECT_CALL_IN_SCOPE(completed, Run, sequence->Start()); +} + +TEST(InteractionSequenceTest, NameElement_ElementHidden_NamedBeforeSequenceAndHiddenBeforeSequence) { UNCALLED_MOCK_CALLBACK(InteractionSequence::AbortedCallback, aborted); UNCALLED_MOCK_CALLBACK(InteractionSequence::CompletedCallback, completed);
diff --git a/ui/base/x/BUILD.gn b/ui/base/x/BUILD.gn index 3cb5ed7..188e69e 100644 --- a/ui/base/x/BUILD.gn +++ b/ui/base/x/BUILD.gn
@@ -50,8 +50,6 @@ "x11_software_bitmap_presenter.h", "x11_topmost_window_finder.cc", "x11_topmost_window_finder.h", - "x11_ui_thread.cc", - "x11_ui_thread.h", "x11_user_input_monitor.cc", "x11_user_input_monitor.h", "x11_util.cc",
diff --git a/ui/base/x/x11_ui_thread.cc b/ui/base/x/x11_ui_thread.cc deleted file mode 100644 index 86111b3..0000000 --- a/ui/base/x/x11_ui_thread.cc +++ /dev/null
@@ -1,49 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "ui/base/x/x11_ui_thread.h" - -#include "ui/events/platform/x11/x11_event_source.h" -#include "ui/gfx/x/connection.h" - -namespace ui { - -namespace { - -x11::Connection* g_connection = nullptr; - -} - -X11UiThread::X11UiThread(const std::string& thread_name) - : base::Thread(thread_name) { - connection_.reset(g_connection); - g_connection = nullptr; - // When using in-process GPU, g_connection doesn't get set. But we can just - // open a new connection now since there's no GPU sandbox in place. - if (!connection_) - connection_ = x11::Connection::Get()->Clone(); - connection_->DetachFromSequence(); -} - -X11UiThread::~X11UiThread() = default; - -void X11UiThread::SetConnection(x11::Connection* connection) { - DCHECK(!g_connection); - g_connection = connection; -} - -void X11UiThread::Init() { - // Connection and X11EventSource make use of TLS, so these calls must be made - // on the thread, not in the constructor/destructor. - auto* connection = connection_.get(); - x11::Connection::Set(std::move(connection_)); - event_source_ = std::make_unique<X11EventSource>(connection); -} - -void X11UiThread::CleanUp() { - event_source_.reset(); - connection_.reset(); -} - -} // namespace ui \ No newline at end of file
diff --git a/ui/base/x/x11_ui_thread.h b/ui/base/x/x11_ui_thread.h deleted file mode 100644 index 8b9bcbc..0000000 --- a/ui/base/x/x11_ui_thread.h +++ /dev/null
@@ -1,48 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef UI_BASE_X_X11_UI_THREAD_H_ -#define UI_BASE_X_X11_UI_THREAD_H_ - -#include "base/component_export.h" -#include "base/threading/thread.h" - -namespace x11 { -class Connection; -} - -namespace ui { - -class X11EventSource; - -// A thread-local x11::Connection may be used on this thread, stored in TLS and -// obtained via x11::Connection::Get(). X11 events for the connection may also -// dispatch events on this thread. This thread must be started as TYPE_UI. -// TODO(thomasanderson): This can be removed once Linux switches to ozone. -class COMPONENT_EXPORT(UI_BASE_X) X11UiThread : public base::Thread { - public: - explicit X11UiThread(const std::string& thread_name); - - ~X11UiThread() override; - - X11UiThread(const X11UiThread&) = delete; - X11UiThread& operator=(const X11UiThread&) = delete; - - // Sets the global connection which will have its ownership transferred to the - // next X11UiThread created. - static void SetConnection(x11::Connection* connection); - - protected: - // base::Thread: - void Init() override; - void CleanUp() override; - - private: - std::unique_ptr<x11::Connection> connection_; - std::unique_ptr<X11EventSource> event_source_; -}; - -} // namespace ui - -#endif // UI_BASE_X_X11_UI_THREAD_H_
diff --git a/ui/chromeos/styles/cros_colors.json5 b/ui/chromeos/styles/cros_colors.json5 index c28d558..17009b9 100644 --- a/ui/chromeos/styles/cros_colors.json5 +++ b/ui/chromeos/styles/cros_colors.json5
@@ -472,6 +472,12 @@ toast_icon_color: "$color_primary_inverted", toast_icon_color_warning: "$color_warning_inverted", toast_icon_color_error: "$color_alert_inverted", + + /* Drag selection box */ + selection_outline: { + light: "rgba($black_rgb, 0.1)", + dark: "rgba($white_rgb, 0.12)", + } }, opacities: { disabled_opacity: 0.38,
diff --git a/ui/compositor/layer.cc b/ui/compositor/layer.cc index 7c42ec8..8510e2f53 100644 --- a/ui/compositor/layer.cc +++ b/ui/compositor/layer.cc
@@ -1378,7 +1378,6 @@ children_.erase(children_.begin() + child_i); children_.insert(children_.begin() + dest_i, child); - child->cc_layer_->RemoveFromParent(); cc_layer_->InsertChild(child->cc_layer_.get(), dest_i); }
diff --git a/ui/events/test/events_test_utils_x11.cc b/ui/events/test/events_test_utils_x11.cc index 3dc96d3..c5b1f4a 100644 --- a/ui/events/test/events_test_utils_x11.cc +++ b/ui/events/test/events_test_utils_x11.cc
@@ -121,7 +121,7 @@ event.event_y = ToFp1616(location.y()), event.event = x11::Connection::Get()->default_root(); event.button_mask = {0, 0}; - return x11::Event(std::move(event)); + return x11::Event(false, std::move(event)); } } // namespace @@ -142,7 +142,7 @@ .same_screen = true, }; - x11::Event x11_event(key_event); + x11::Event x11_event(false, key_event); event_ = std::move(x11_event); } @@ -158,7 +158,7 @@ .same_screen = true, }; - x11::Event x11_event(motion_event); + x11::Event x11_event(false, motion_event); event_ = std::move(x11_event); } @@ -176,7 +176,7 @@ .same_screen = true, }; - x11::Event x11_event(button_event); + x11::Event x11_event(false, button_event); event_ = std::move(x11_event); }
diff --git a/ui/events/x/events_x_utils.cc b/ui/events/x/events_x_utils.cc index 581f3c8..5bfe4d9 100644 --- a/ui/events/x/events_x_utils.cc +++ b/ui/events/x/events_x_utils.cc
@@ -184,8 +184,8 @@ fabricated_by_xim ? ui::EF_IME_FABRICATED_KEY : 0; #endif - return GetEventFlagsFromXState(state) | (key->send_event ? ui::EF_FINAL : 0) | - ime_fabricated_flag; + return GetEventFlagsFromXState(state) | + (xev.send_event() ? ui::EF_FINAL : 0) | ime_fabricated_flag; } int GetEventFlagsFromXGenericEvent(const x11::Event& x11_event) { @@ -194,7 +194,7 @@ DCHECK(xievent->opcode == x11::Input::DeviceEvent::KeyPress || xievent->opcode == x11::Input::DeviceEvent::KeyRelease); return GetEventFlagsFromXState(xievent->mods.effective) | - (xievent->send_event ? ui::EF_FINAL : 0); + (x11_event.send_event() ? ui::EF_FINAL : 0); } // Get the event flag for the button in XButtonEvent. During a ButtonPress
diff --git a/ui/file_manager/file_manager/common/js/util.js b/ui/file_manager/file_manager/common/js/util.js index 7931ec35..6b9949e 100644 --- a/ui/file_manager/file_manager/common/js/util.js +++ b/ui/file_manager/file_manager/common/js/util.js
@@ -1370,6 +1370,14 @@ }; /** + * Returns true if GuestOsFiles flag is enabled. + * @return {boolean} + */ +util.isGuestOsEnabled = () => { + return loadTimeData.getBoolean('GUEST_OS'); +}; + +/** * Retrieves all entries inside the given |rootEntry|. * @param {!DirectoryEntry} rootEntry * @param {function(!Array<!Entry>)} entriesCallback Called when some chunk of
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 2126ab0..2b3d1953 100644 --- a/ui/file_manager/file_manager/foreground/css/file_manager.css +++ b/ui/file_manager/file_manager/foreground/css/file_manager.css
@@ -39,7 +39,7 @@ display: flex; flex: auto; flex-direction: column; - font-size: 81%; + font-size: 13px; height: 100%; margin: 0; padding: 0; @@ -47,19 +47,6 @@ width: 100%; } -body.files-ng { - font-size: 13px; -} - -button:focus, -input[type='button']:focus, -input[type='submit']:focus, -select:focus, -a:focus { - background-color: rgba(255, 255, 255, 20%); - outline-color: rgb(77, 144, 254); -} - /* Drop opacity of selected rows to give a visual feedback on copy/cut * operation. */ .blink { @@ -123,7 +110,7 @@ overflow-y: hidden; } -#directory-tree[files-ng] .tree-item[section-start]::before { +#directory-tree .tree-item[section-start]::before { border-bottom: 1px solid var(--cros-separator-color); content: ''; display: block; @@ -131,7 +118,7 @@ width: 100%; } -#directory-tree[files-ng] .tree-row { +#directory-tree .tree-row { cursor: pointer; height: auto; padding: 4px 0; @@ -440,37 +427,29 @@ /* Breadcrumbs and things under the title but above the list view. */ .dialog-header { align-items: center; + background: none; + border-bottom: 1px solid var(--cros-separator-color); box-sizing: border-box; - color: white; + color: var(--cros-text-color-secondary); display: flex; flex: none; flex-direction: row; - height: 48px; - transition: background 220ms ease; -} - -.dialog-header.files-ng { - background: none; - border-bottom: 1px solid var(--cros-separator-color); - color: var(--cros-text-color-secondary); font-size: 14px; height: 56px; overflow: hidden; + transition: background 220ms ease; } body.check-select .dialog-header { border-bottom: 1px solid var(--cros-separator-color); border-top: 1px solid transparent; -} - -body.check-select .dialog-header.files-ng { color: var(--cros-text-color-prominent); } -/* Display a grey border during check-select mode if we're in a dialog. (This +/* Display a border during check-select mode if we're in a dialog. (This can only happen in an open-multi-file dialog). */ body[type='open-multi-file'].check-select .dialog-header { - border-top: 1px solid rgb(219, 219, 219); + border-top: 1px solid var(--cros-bg-color); } .dialog-header > .spacer { @@ -479,21 +458,6 @@ .dialog-header cr-button, .dialog-header button { - border: none; - border-radius: 2px; - box-sizing: border-box; - cursor: pointer; - height: 32px; - margin: 0 8px; - min-width: 32px; - padding: 0; - position: relative; - text-transform: uppercase; - z-index: 1; -} - -.dialog-header.files-ng cr-button, -.dialog-header.files-ng button { --active-bg: var(--cros-ripple-color); --hover-bg-color: var(--cros-ripple-color); --ink-color: var(--cros-ripple-color); @@ -501,10 +465,16 @@ --text-color: currentColor; border: 1px solid transparent; border-radius: 18px; + box-sizing: border-box; color: var(--cros-text-color-primary); + cursor: pointer; height: 36px; margin: 0 6px; min-width: 36px; + padding: 0; + position: relative; + text-transform: uppercase; + z-index: 1; } html.pointer-active .dialog-header.files-ng cr-button:not(:active):hover { @@ -541,8 +511,8 @@ border: 1px solid var(--cros-focus-ring-color); } -.dialog-header.files-ng files-ripple, -.dialog-header.files-ng files-toggle-ripple { +.dialog-header files-ripple, +.dialog-header files-toggle-ripple { display: none; } @@ -551,25 +521,20 @@ color: var(--cros-text-color-primary); } -.dialog-header .icon-button > paper-ripple, -.dialog-header .ripples > paper-ripple { - color: black; -} - body.check-select .dialog-header button paper-ripple { color: var(--cros-text-color-primary); } /** Avoid highlighting if element doesn't have focus by tab (tabindex=-1) * or if focusing during mouse click event ":active" pseudo-selector. */ -html.focus-outline-visible.files-ng .dialog-header +html.focus-outline-visible .dialog-header .menu-button:focus:not([tabindex='-1']):not(:active) { background-color: transparent; } body.check-select .dialog-header .menu-button:focus:not([tabindex='-1']):not(:active) { - background-color: rgba(153, 153, 153, 20%); + background-color: var(--cros-ripple-color); } .dialog-header iron-icon, @@ -1407,9 +1372,9 @@ #file-list .drag-selection-border { -webkit-box-sizing: border-box; - background-color: rgba(255, 255, 255, 30%); - border: 2px solid rgba(255, 255, 255, 60%); - outline: 1px solid rgba(0, 0, 0, 10%); + background-color: rgba(var(--cros-bg-color-rgb), 30%); + border: 2px solid rgba(var(--cros-bg-color-rgb), 60%); + outline: 1px solid var(--cros-selection-outline); position: absolute; z-index: 2; } @@ -1434,20 +1399,6 @@ top: 64px; } -body.files-ng .downloads-warning, -body.files-ng .trash-warning { - align-items: center; - border-bottom: 1px solid var(--cr-separator-color, rgb(224, 224, 224)); - display: flex; - flex: none; - flex-direction: row; - height: 40px; - opacity: 1; - transition: height 300ms cubic-bezier(0.4, 0, 0.2, 1) 0s, - opacity 150ms ease 50ms; - visibility: visible; -} - @keyframes heightAnimation { 0% { display: flex; @@ -1681,7 +1632,7 @@ } .badge { - background-color: white; + background-color: var(--cros-bg-color); background-position: center; background-repeat: no-repeat; border-radius: 2px; @@ -1724,8 +1675,10 @@ padding-top: 8px; } -body.files-ng #default-task-dialog.bottom-shadow::after { - background: linear-gradient(180deg, #FFF 0, rgba(255, 255, 255, 0) 100%); +#default-task-dialog.bottom-shadow::after { + background: linear-gradient(180deg, + var(--cros-bg-color) 0, + var(--cros-bg-color) 100%); bottom: 24px; content: ''; height: 40px; @@ -1736,6 +1689,14 @@ width: 100% } +@media (prefers-color-scheme: dark) { + #default-task-dialog.bottom-shadow::after { + background: linear-gradient(180deg, + var(--cros-bg-color-elevation-2) 0, + var(--cros-bg-color-elevation-2) 100%); + } +} + #default-tasks-list li { height: 40px; line-height: 40px; @@ -1840,7 +1801,7 @@ @keyframes acceptsBlink { 0% { background-color: transparent; - color: rgb(90, 90, 90); + color: var(--cros-ripple-color); } }
diff --git a/ui/file_manager/file_manager/foreground/elements/files_quick_view.css b/ui/file_manager/file_manager/foreground/elements/files_quick_view.css index 2002c84..810f9518 100644 --- a/ui/file_manager/file_manager/foreground/elements/files_quick_view.css +++ b/ui/file_manager/file_manager/foreground/elements/files_quick_view.css
@@ -31,10 +31,6 @@ outline: none; } -dialog::backdrop { - background-color: var(--cros-app-shield-80); -} - dialog#delete-confirm-dialog::backdrop { background-color: transparent; }
diff --git a/ui/gfx/x/event.cc b/ui/gfx/x/event.cc index 68d6946..3d695d1 100644 --- a/ui/gfx/x/event.cc +++ b/ui/gfx/x/event.cc
@@ -23,17 +23,17 @@ Connection* connection) { auto* xcb_event = reinterpret_cast<xcb_generic_event_t*>( const_cast<uint8_t*>(event_bytes->data())); + uint8_t response_type = xcb_event->response_type & ~kSendEventMask; + send_event_ = xcb_event->response_type & kSendEventMask; sequence_ = xcb_event->full_sequence; // KeymapNotify events are the only events that don't have a sequence. - if ((xcb_event->response_type & ~kSendEventMask) != - KeymapNotifyEvent::opcode) { + if (response_type != KeymapNotifyEvent::opcode) { // On the wire, events are 32 bytes except for generic events which are // trailed by additional data. XCB inserts an extended 4-byte sequence // between the 32-byte event and the additional data, so we need to shift // the additional data over by 4 bytes so the event is back in its wire // format, which is what Xlib and XProto are expecting. - if ((xcb_event->response_type & ~kSendEventMask) == - GeGenericEvent::opcode) { + if (response_type == GeGenericEvent::opcode) { auto* ge = reinterpret_cast<xcb_ge_event_t*>(xcb_event); constexpr size_t ge_length = sizeof(xcb_raw_generic_event_t); constexpr size_t offset = sizeof(ge->full_sequence);
diff --git a/ui/gfx/x/event.h b/ui/gfx/x/event.h index ed4f9b0..dd23351 100644 --- a/ui/gfx/x/event.h +++ b/ui/gfx/x/event.h
@@ -25,8 +25,9 @@ class COMPONENT_EXPORT(X11) Event { public: template <typename T> - explicit Event(T&& xproto_event) { + Event(bool send_event, T&& xproto_event) { using DecayT = std::decay_t<T>; + send_event_ = send_event; sequence_ = xproto_event.sequence; type_id_ = DecayT::type_id; deleter_ = [](void* event) { delete reinterpret_cast<DecayT*>(event); }; @@ -62,6 +63,8 @@ return const_cast<Event*>(this)->As<T>(); } + bool send_event() const { return send_event_; } + uint32_t sequence() const { return sequence_; } Window window() const { return window_ ? *window_ : Window::None; } @@ -79,6 +82,9 @@ void Dealloc(); + // True if this event was sent from another X client. False if this event + // was sent by the X server. + bool send_event_ = false; uint16_t sequence_ = 0; // XProto event state.
diff --git a/ui/gfx/x/gen_xproto.py b/ui/gfx/x/gen_xproto.py index c631e54..bb0a6d89 100644 --- a/ui/gfx/x/gen_xproto.py +++ b/ui/gfx/x/gen_xproto.py
@@ -761,7 +761,6 @@ for (y, x) in event.enum_opcodes.items()] for opcode, opname in sorted(items): self.write('%s = %s,' % (opname, opcode)) - self.write('bool send_event{};') self.declare_fields(event.fields) self.write() window_field = self.get_window_field(event) @@ -1491,7 +1490,6 @@ if len(event.opcodes) > 1: self.write('{0} = static_cast<decltype({0})>({1});'.format( 'event_->opcode', opcode)) - self.write('event_->send_event = send_event;') self.write('event->event_ = event_;') self.write('event->window_ = event_->GetWindow();') self.write('return;') @@ -1519,7 +1517,6 @@ self.write(cast % ('ev', 'xcb_generic_event_t')) self.write(cast % ('ge', 'xcb_ge_generic_event_t')) self.write('auto evtype = ev->response_type & ~kSendEventMask;') - self.write('bool send_event = ev->response_type & kSendEventMask;') self.write() for name, event, proto in self.events: self.gen_event(name, event, proto)
diff --git a/ui/gfx/x/generated_protos/bigreq.cc b/ui/gfx/x/generated_protos/bigreq.cc index 8ad0c82..bf527ba 100644 --- a/ui/gfx/x/generated_protos/bigreq.cc +++ b/ui/gfx/x/generated_protos/bigreq.cc
@@ -40,6 +40,7 @@ #include "bigreq.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/bigreq.h b/ui/gfx/x/generated_protos/bigreq.h index 46d12de2..26273c3 100644 --- a/ui/gfx/x/generated_protos/bigreq.h +++ b/ui/gfx/x/generated_protos/bigreq.h
@@ -41,9 +41,11 @@ #ifndef UI_GFX_X_GENERATED_PROTOS_BIGREQ_H_ #define UI_GFX_X_GENERATED_PROTOS_BIGREQ_H_ +#include <array> #include <cstddef> #include <cstdint> #include <cstring> +#include <vector> #include "base/component_export.h" #include "base/files/scoped_file.h"
diff --git a/ui/gfx/x/generated_protos/composite.cc b/ui/gfx/x/generated_protos/composite.cc index 5fda7238..597ccec 100644 --- a/ui/gfx/x/generated_protos/composite.cc +++ b/ui/gfx/x/generated_protos/composite.cc
@@ -40,6 +40,7 @@ #include "composite.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/damage.cc b/ui/gfx/x/generated_protos/damage.cc index bfd9c665..81b2748 100644 --- a/ui/gfx/x/generated_protos/damage.cc +++ b/ui/gfx/x/generated_protos/damage.cc
@@ -40,6 +40,7 @@ #include "damage.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/damage.h b/ui/gfx/x/generated_protos/damage.h index bcfd8c4e..581e8a6 100644 --- a/ui/gfx/x/generated_protos/damage.h +++ b/ui/gfx/x/generated_protos/damage.h
@@ -99,7 +99,6 @@ struct NotifyEvent { static constexpr int type_id = 1; static constexpr uint8_t opcode = 0; - bool send_event{}; ReportLevel level{}; uint16_t sequence{}; Drawable drawable{};
diff --git a/ui/gfx/x/generated_protos/dpms.cc b/ui/gfx/x/generated_protos/dpms.cc index dd007a3f..a517786 100644 --- a/ui/gfx/x/generated_protos/dpms.cc +++ b/ui/gfx/x/generated_protos/dpms.cc
@@ -40,6 +40,7 @@ #include "dpms.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/dri2.cc b/ui/gfx/x/generated_protos/dri2.cc index 0e5eca2..c080928 100644 --- a/ui/gfx/x/generated_protos/dri2.cc +++ b/ui/gfx/x/generated_protos/dri2.cc
@@ -40,6 +40,7 @@ #include "dri2.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/dri2.h b/ui/gfx/x/generated_protos/dri2.h index 5d4a6bdf..357edaa 100644 --- a/ui/gfx/x/generated_protos/dri2.h +++ b/ui/gfx/x/generated_protos/dri2.h
@@ -121,7 +121,6 @@ struct BufferSwapCompleteEvent { static constexpr int type_id = 2; static constexpr uint8_t opcode = 0; - bool send_event{}; uint16_t sequence{}; EventType event_type{}; Drawable drawable{}; @@ -139,7 +138,6 @@ struct InvalidateBuffersEvent { static constexpr int type_id = 3; static constexpr uint8_t opcode = 1; - bool send_event{}; uint16_t sequence{}; Drawable drawable{};
diff --git a/ui/gfx/x/generated_protos/ge.cc b/ui/gfx/x/generated_protos/ge.cc index 8afc628b..6989e30 100644 --- a/ui/gfx/x/generated_protos/ge.cc +++ b/ui/gfx/x/generated_protos/ge.cc
@@ -40,6 +40,7 @@ #include "ge.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/ge.h b/ui/gfx/x/generated_protos/ge.h index 5e36176..683c139c 100644 --- a/ui/gfx/x/generated_protos/ge.h +++ b/ui/gfx/x/generated_protos/ge.h
@@ -41,9 +41,11 @@ #ifndef UI_GFX_X_GENERATED_PROTOS_GE_H_ #define UI_GFX_X_GENERATED_PROTOS_GE_H_ +#include <array> #include <cstddef> #include <cstdint> #include <cstring> +#include <vector> #include "base/component_export.h" #include "base/files/scoped_file.h"
diff --git a/ui/gfx/x/generated_protos/glx.cc b/ui/gfx/x/generated_protos/glx.cc index 3ae9c18c..f0adfb92 100644 --- a/ui/gfx/x/generated_protos/glx.cc +++ b/ui/gfx/x/generated_protos/glx.cc
@@ -40,6 +40,7 @@ #include "glx.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/glx.h b/ui/gfx/x/generated_protos/glx.h index cc805bb..cd5810e 100644 --- a/ui/gfx/x/generated_protos/glx.h +++ b/ui/gfx/x/generated_protos/glx.h
@@ -290,7 +290,6 @@ struct PbufferClobberEvent { static constexpr int type_id = 4; static constexpr uint8_t opcode = 0; - bool send_event{}; uint16_t sequence{}; uint16_t event_type{}; uint16_t draw_type{}; @@ -311,7 +310,6 @@ struct BufferSwapCompleteEvent { static constexpr int type_id = 5; static constexpr uint8_t opcode = 1; - bool send_event{}; uint16_t sequence{}; uint16_t event_type{}; Drawable drawable{};
diff --git a/ui/gfx/x/generated_protos/present.cc b/ui/gfx/x/generated_protos/present.cc index b4edda68..16aeff7 100644 --- a/ui/gfx/x/generated_protos/present.cc +++ b/ui/gfx/x/generated_protos/present.cc
@@ -40,6 +40,7 @@ #include "present.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/present.h b/ui/gfx/x/generated_protos/present.h index dcfd695..d78c2d5 100644 --- a/ui/gfx/x/generated_protos/present.h +++ b/ui/gfx/x/generated_protos/present.h
@@ -133,7 +133,6 @@ struct GenericEvent { static constexpr int type_id = 6; static constexpr uint8_t opcode = 0; - bool send_event{}; uint8_t extension{}; uint16_t sequence{}; uint32_t length{}; @@ -146,7 +145,6 @@ struct ConfigureNotifyEvent { static constexpr int type_id = 7; static constexpr uint8_t opcode = 0; - bool send_event{}; uint16_t sequence{}; Event event{}; Window window{}; @@ -166,7 +164,6 @@ struct CompleteNotifyEvent { static constexpr int type_id = 8; static constexpr uint8_t opcode = 1; - bool send_event{}; uint16_t sequence{}; CompleteKind kind{}; CompleteMode mode{}; @@ -182,7 +179,6 @@ struct IdleNotifyEvent { static constexpr int type_id = 9; static constexpr uint8_t opcode = 2; - bool send_event{}; uint16_t sequence{}; Event event{}; Window window{}; @@ -196,7 +192,6 @@ struct RedirectNotifyEvent { static constexpr int type_id = 10; static constexpr uint8_t opcode = 3; - bool send_event{}; uint16_t sequence{}; uint8_t update_window{}; Event event{};
diff --git a/ui/gfx/x/generated_protos/randr.cc b/ui/gfx/x/generated_protos/randr.cc index 7228c86..1b83849a 100644 --- a/ui/gfx/x/generated_protos/randr.cc +++ b/ui/gfx/x/generated_protos/randr.cc
@@ -40,6 +40,7 @@ #include "randr.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h> @@ -2494,7 +2495,7 @@ buf.Write(&crtc); // size - size = red.size(); + size = blue.size(); buf.Write(&size); // pad0
diff --git a/ui/gfx/x/generated_protos/randr.h b/ui/gfx/x/generated_protos/randr.h index 1f420bb..8367b22 100644 --- a/ui/gfx/x/generated_protos/randr.h +++ b/ui/gfx/x/generated_protos/randr.h
@@ -219,7 +219,6 @@ struct ScreenChangeNotifyEvent { static constexpr int type_id = 11; static constexpr uint8_t opcode = 0; - bool send_event{}; Rotation rotation{}; uint16_t sequence{}; Time timestamp{}; @@ -254,7 +253,6 @@ struct NotifyEvent { static constexpr int type_id = 12; static constexpr uint8_t opcode = 1; - bool send_event{}; uint16_t sequence{}; struct Cc { Time timestamp{};
diff --git a/ui/gfx/x/generated_protos/read_event.cc b/ui/gfx/x/generated_protos/read_event.cc index a6a308f..bc58a45c 100644 --- a/ui/gfx/x/generated_protos/read_event.cc +++ b/ui/gfx/x/generated_protos/read_event.cc
@@ -83,7 +83,6 @@ auto* ev = reinterpret_cast<const xcb_generic_event_t*>(buf); auto* ge = reinterpret_cast<const xcb_ge_generic_event_t*>(buf); auto evtype = ev->response_type & ~kSendEventMask; - bool send_event = ev->response_type & kSendEventMask; if (conn->damage().present() && evtype - conn->damage().first_event() == Damage::NotifyEvent::opcode) { @@ -93,7 +92,6 @@ }; auto* event_ = new Damage::NotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -107,7 +105,6 @@ }; auto* event_ = new Dri2::BufferSwapCompleteEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -121,7 +118,6 @@ }; auto* event_ = new Dri2::InvalidateBuffersEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -135,7 +131,6 @@ }; auto* event_ = new Glx::PbufferClobberEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -149,7 +144,6 @@ }; auto* event_ = new Glx::BufferSwapCompleteEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -163,7 +157,6 @@ }; auto* event_ = new Present::GenericEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -178,7 +171,6 @@ }; auto* event_ = new Present::ConfigureNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -193,7 +185,6 @@ }; auto* event_ = new Present::CompleteNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -208,7 +199,6 @@ }; auto* event_ = new Present::IdleNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -223,7 +213,6 @@ }; auto* event_ = new Present::RedirectNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -237,7 +226,6 @@ }; auto* event_ = new RandR::ScreenChangeNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -251,7 +239,6 @@ }; auto* event_ = new RandR::NotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -266,7 +253,6 @@ }; auto* event_ = new ScreenSaver::NotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -280,7 +266,6 @@ }; auto* event_ = new Shape::NotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -294,7 +279,6 @@ }; auto* event_ = new Shm::CompletionEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -308,7 +292,6 @@ }; auto* event_ = new Sync::CounterNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -322,7 +305,6 @@ }; auto* event_ = new Sync::AlarmNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -336,7 +318,6 @@ }; auto* event_ = new XFixes::SelectionNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -350,7 +331,6 @@ }; auto* event_ = new XFixes::CursorNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -364,7 +344,6 @@ }; auto* event_ = new Input::DeviceValuatorEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -372,19 +351,19 @@ if (conn->xinput().present() && (evtype - conn->xinput().first_event() == - Input::LegacyDeviceEvent::DeviceButtonRelease || - evtype - conn->xinput().first_event() == - Input::LegacyDeviceEvent::ProximityIn || + Input::LegacyDeviceEvent::DeviceKeyPress || evtype - conn->xinput().first_event() == Input::LegacyDeviceEvent::DeviceKeyRelease || evtype - conn->xinput().first_event() == Input::LegacyDeviceEvent::DeviceButtonPress || evtype - conn->xinput().first_event() == - Input::LegacyDeviceEvent::ProximityOut || + Input::LegacyDeviceEvent::DeviceButtonRelease || evtype - conn->xinput().first_event() == - Input::LegacyDeviceEvent::DeviceKeyPress || + Input::LegacyDeviceEvent::DeviceMotionNotify || evtype - conn->xinput().first_event() == - Input::LegacyDeviceEvent::DeviceMotionNotify)) { + Input::LegacyDeviceEvent::ProximityIn || + evtype - conn->xinput().first_event() == + Input::LegacyDeviceEvent::ProximityOut)) { event->type_id_ = 21; event->deleter_ = [](void* event) { delete reinterpret_cast<Input::LegacyDeviceEvent*>(event); @@ -393,7 +372,6 @@ ReadEvent(event_, buffer); event_->opcode = static_cast<decltype(event_->opcode)>( evtype - conn->xinput().first_event()); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -410,7 +388,6 @@ ReadEvent(event_, buffer); event_->opcode = static_cast<decltype(event_->opcode)>( evtype - conn->xinput().first_event()); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -424,7 +401,6 @@ }; auto* event_ = new Input::DeviceStateNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -438,7 +414,6 @@ }; auto* event_ = new Input::DeviceMappingNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -452,7 +427,6 @@ }; auto* event_ = new Input::ChangeDeviceNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -467,7 +441,6 @@ }; auto* event_ = new Input::DeviceKeyStateNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -482,7 +455,6 @@ }; auto* event_ = new Input::DeviceButtonStateNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -497,7 +469,6 @@ }; auto* event_ = new Input::DevicePresenceNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -512,7 +483,6 @@ }; auto* event_ = new Input::DevicePropertyNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -527,7 +497,6 @@ }; auto* event_ = new Input::DeviceChangedEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -535,14 +504,14 @@ if (evtype == GeGenericEvent::opcode && conn->xinput().present() && ge->extension == conn->xinput().major_opcode() && - (ge->event_type == Input::DeviceEvent::ButtonPress || - ge->event_type == Input::DeviceEvent::TouchEnd || + (ge->event_type == Input::DeviceEvent::KeyPress || ge->event_type == Input::DeviceEvent::KeyRelease || - ge->event_type == Input::DeviceEvent::TouchUpdate || - ge->event_type == Input::DeviceEvent::KeyPress || + ge->event_type == Input::DeviceEvent::ButtonPress || + ge->event_type == Input::DeviceEvent::ButtonRelease || ge->event_type == Input::DeviceEvent::Motion || ge->event_type == Input::DeviceEvent::TouchBegin || - ge->event_type == Input::DeviceEvent::ButtonRelease)) { + ge->event_type == Input::DeviceEvent::TouchUpdate || + ge->event_type == Input::DeviceEvent::TouchEnd)) { event->type_id_ = 31; event->deleter_ = [](void* event) { delete reinterpret_cast<Input::DeviceEvent*>(event); @@ -550,7 +519,6 @@ auto* event_ = new Input::DeviceEvent; ReadEvent(event_, buffer); event_->opcode = static_cast<decltype(event_->opcode)>(ge->event_type); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -558,10 +526,10 @@ if (evtype == GeGenericEvent::opcode && conn->xinput().present() && ge->extension == conn->xinput().major_opcode() && - (ge->event_type == Input::CrossingEvent::Leave || + (ge->event_type == Input::CrossingEvent::Enter || + ge->event_type == Input::CrossingEvent::Leave || ge->event_type == Input::CrossingEvent::FocusIn || - ge->event_type == Input::CrossingEvent::FocusOut || - ge->event_type == Input::CrossingEvent::Enter)) { + ge->event_type == Input::CrossingEvent::FocusOut)) { event->type_id_ = 32; event->deleter_ = [](void* event) { delete reinterpret_cast<Input::CrossingEvent*>(event); @@ -569,7 +537,6 @@ auto* event_ = new Input::CrossingEvent; ReadEvent(event_, buffer); event_->opcode = static_cast<decltype(event_->opcode)>(ge->event_type); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -584,7 +551,6 @@ }; auto* event_ = new Input::HierarchyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -599,7 +565,6 @@ }; auto* event_ = new Input::PropertyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -607,14 +572,14 @@ if (evtype == GeGenericEvent::opcode && conn->xinput().present() && ge->extension == conn->xinput().major_opcode() && - (ge->event_type == Input::RawDeviceEvent::RawTouchEnd || - ge->event_type == Input::RawDeviceEvent::RawTouchUpdate || - ge->event_type == Input::RawDeviceEvent::RawTouchBegin || + (ge->event_type == Input::RawDeviceEvent::RawKeyPress || + ge->event_type == Input::RawDeviceEvent::RawKeyRelease || + ge->event_type == Input::RawDeviceEvent::RawButtonPress || ge->event_type == Input::RawDeviceEvent::RawButtonRelease || ge->event_type == Input::RawDeviceEvent::RawMotion || - ge->event_type == Input::RawDeviceEvent::RawButtonPress || - ge->event_type == Input::RawDeviceEvent::RawKeyRelease || - ge->event_type == Input::RawDeviceEvent::RawKeyPress)) { + ge->event_type == Input::RawDeviceEvent::RawTouchBegin || + ge->event_type == Input::RawDeviceEvent::RawTouchUpdate || + ge->event_type == Input::RawDeviceEvent::RawTouchEnd)) { event->type_id_ = 35; event->deleter_ = [](void* event) { delete reinterpret_cast<Input::RawDeviceEvent*>(event); @@ -622,7 +587,6 @@ auto* event_ = new Input::RawDeviceEvent; ReadEvent(event_, buffer); event_->opcode = static_cast<decltype(event_->opcode)>(ge->event_type); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -637,7 +601,6 @@ }; auto* event_ = new Input::TouchOwnershipEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -645,8 +608,8 @@ if (evtype == GeGenericEvent::opcode && conn->xinput().present() && ge->extension == conn->xinput().major_opcode() && - (ge->event_type == Input::BarrierEvent::Leave || - ge->event_type == Input::BarrierEvent::Hit)) { + (ge->event_type == Input::BarrierEvent::Hit || + ge->event_type == Input::BarrierEvent::Leave)) { event->type_id_ = 37; event->deleter_ = [](void* event) { delete reinterpret_cast<Input::BarrierEvent*>(event); @@ -654,7 +617,6 @@ auto* event_ = new Input::BarrierEvent; ReadEvent(event_, buffer); event_->opcode = static_cast<decltype(event_->opcode)>(ge->event_type); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -668,7 +630,6 @@ }; auto* event_ = new Xkb::NewKeyboardNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -682,7 +643,6 @@ }; auto* event_ = new Xkb::MapNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -696,7 +656,6 @@ }; auto* event_ = new Xkb::StateNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -710,7 +669,6 @@ }; auto* event_ = new Xkb::ControlsNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -724,7 +682,6 @@ }; auto* event_ = new Xkb::IndicatorStateNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -738,7 +695,6 @@ }; auto* event_ = new Xkb::IndicatorMapNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -752,7 +708,6 @@ }; auto* event_ = new Xkb::NamesNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -766,7 +721,6 @@ }; auto* event_ = new Xkb::CompatMapNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -780,7 +734,6 @@ }; auto* event_ = new Xkb::BellNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -794,7 +747,6 @@ }; auto* event_ = new Xkb::ActionMessageEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -808,7 +760,6 @@ }; auto* event_ = new Xkb::AccessXNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -822,7 +773,6 @@ }; auto* event_ = new Xkb::ExtensionDeviceNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -836,7 +786,6 @@ }; auto* event_ = new XPrint::NotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -850,13 +799,12 @@ }; auto* event_ = new XPrint::AttributNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; } - if ((evtype == KeyEvent::Release || evtype == KeyEvent::Press)) { + if ((evtype == KeyEvent::Press || evtype == KeyEvent::Release)) { event->type_id_ = 52; event->deleter_ = [](void* event) { delete reinterpret_cast<KeyEvent*>(event); @@ -864,13 +812,12 @@ auto* event_ = new KeyEvent; ReadEvent(event_, buffer); event_->opcode = static_cast<decltype(event_->opcode)>(evtype); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; } - if ((evtype == ButtonEvent::Release || evtype == ButtonEvent::Press)) { + if ((evtype == ButtonEvent::Press || evtype == ButtonEvent::Release)) { event->type_id_ = 53; event->deleter_ = [](void* event) { delete reinterpret_cast<ButtonEvent*>(event); @@ -878,7 +825,6 @@ auto* event_ = new ButtonEvent; ReadEvent(event_, buffer); event_->opcode = static_cast<decltype(event_->opcode)>(evtype); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -891,7 +837,6 @@ }; auto* event_ = new MotionNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -906,13 +851,12 @@ auto* event_ = new CrossingEvent; ReadEvent(event_, buffer); event_->opcode = static_cast<decltype(event_->opcode)>(evtype); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; } - if ((evtype == FocusEvent::Out || evtype == FocusEvent::In)) { + if ((evtype == FocusEvent::In || evtype == FocusEvent::Out)) { event->type_id_ = 56; event->deleter_ = [](void* event) { delete reinterpret_cast<FocusEvent*>(event); @@ -920,7 +864,6 @@ auto* event_ = new FocusEvent; ReadEvent(event_, buffer); event_->opcode = static_cast<decltype(event_->opcode)>(evtype); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -933,7 +876,6 @@ }; auto* event_ = new KeymapNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -946,7 +888,6 @@ }; auto* event_ = new ExposeEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -959,7 +900,6 @@ }; auto* event_ = new GraphicsExposureEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -972,7 +912,6 @@ }; auto* event_ = new NoExposureEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -985,7 +924,6 @@ }; auto* event_ = new VisibilityNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -998,7 +936,6 @@ }; auto* event_ = new CreateNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1011,7 +948,6 @@ }; auto* event_ = new DestroyNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1024,7 +960,6 @@ }; auto* event_ = new UnmapNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1037,7 +972,6 @@ }; auto* event_ = new MapNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1050,7 +984,6 @@ }; auto* event_ = new MapRequestEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1063,7 +996,6 @@ }; auto* event_ = new ReparentNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1076,7 +1008,6 @@ }; auto* event_ = new ConfigureNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1089,7 +1020,6 @@ }; auto* event_ = new ConfigureRequestEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1102,7 +1032,6 @@ }; auto* event_ = new GravityNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1115,13 +1044,12 @@ }; auto* event_ = new ResizeRequestEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; } - if ((evtype == CirculateEvent::Request || evtype == CirculateEvent::Notify)) { + if ((evtype == CirculateEvent::Notify || evtype == CirculateEvent::Request)) { event->type_id_ = 72; event->deleter_ = [](void* event) { delete reinterpret_cast<CirculateEvent*>(event); @@ -1129,7 +1057,6 @@ auto* event_ = new CirculateEvent; ReadEvent(event_, buffer); event_->opcode = static_cast<decltype(event_->opcode)>(evtype); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1142,7 +1069,6 @@ }; auto* event_ = new PropertyNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1155,7 +1081,6 @@ }; auto* event_ = new SelectionClearEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1168,7 +1093,6 @@ }; auto* event_ = new SelectionRequestEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1181,7 +1105,6 @@ }; auto* event_ = new SelectionNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1194,7 +1117,6 @@ }; auto* event_ = new ColormapNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1207,7 +1129,6 @@ }; auto* event_ = new ClientMessageEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1220,7 +1141,6 @@ }; auto* event_ = new MappingNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1234,7 +1154,6 @@ }; auto* event_ = new Xv::VideoNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return; @@ -1248,7 +1167,6 @@ }; auto* event_ = new Xv::PortNotifyEvent; ReadEvent(event_, buffer); - event_->send_event = send_event; event->event_ = event_; event->window_ = event_->GetWindow(); return;
diff --git a/ui/gfx/x/generated_protos/record.cc b/ui/gfx/x/generated_protos/record.cc index 3976979..356cce15 100644 --- a/ui/gfx/x/generated_protos/record.cc +++ b/ui/gfx/x/generated_protos/record.cc
@@ -40,6 +40,7 @@ #include "record.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/render.cc b/ui/gfx/x/generated_protos/render.cc index 553afbd9..7784a7b 100644 --- a/ui/gfx/x/generated_protos/render.cc +++ b/ui/gfx/x/generated_protos/render.cc
@@ -40,6 +40,7 @@ #include "render.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h> @@ -2697,7 +2698,7 @@ } // num_stops - num_stops = stops.size(); + num_stops = colors.size(); buf.Write(&num_stops); // stops @@ -2810,7 +2811,7 @@ buf.Write(&outer_radius); // num_stops - num_stops = stops.size(); + num_stops = colors.size(); buf.Write(&num_stops); // stops @@ -2908,7 +2909,7 @@ buf.Write(&angle); // num_stops - num_stops = stops.size(); + num_stops = colors.size(); buf.Write(&num_stops); // stops
diff --git a/ui/gfx/x/generated_protos/res.cc b/ui/gfx/x/generated_protos/res.cc index a17dcff..b803fa1d 100644 --- a/ui/gfx/x/generated_protos/res.cc +++ b/ui/gfx/x/generated_protos/res.cc
@@ -40,6 +40,7 @@ #include "res.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/screensaver.cc b/ui/gfx/x/generated_protos/screensaver.cc index b28f663..ffac336 100644 --- a/ui/gfx/x/generated_protos/screensaver.cc +++ b/ui/gfx/x/generated_protos/screensaver.cc
@@ -40,6 +40,7 @@ #include "screensaver.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/screensaver.h b/ui/gfx/x/generated_protos/screensaver.h index 7f43bcd..3e45718 100644 --- a/ui/gfx/x/generated_protos/screensaver.h +++ b/ui/gfx/x/generated_protos/screensaver.h
@@ -101,7 +101,6 @@ struct NotifyEvent { static constexpr int type_id = 13; static constexpr uint8_t opcode = 0; - bool send_event{}; State state{}; uint16_t sequence{}; Time time{};
diff --git a/ui/gfx/x/generated_protos/shape.cc b/ui/gfx/x/generated_protos/shape.cc index 946080af..fdb9a90 100644 --- a/ui/gfx/x/generated_protos/shape.cc +++ b/ui/gfx/x/generated_protos/shape.cc
@@ -40,6 +40,7 @@ #include "shape.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/shape.h b/ui/gfx/x/generated_protos/shape.h index 7262c39..fa34adc3 100644 --- a/ui/gfx/x/generated_protos/shape.h +++ b/ui/gfx/x/generated_protos/shape.h
@@ -101,7 +101,6 @@ struct NotifyEvent { static constexpr int type_id = 14; static constexpr uint8_t opcode = 0; - bool send_event{}; Sk shape_kind{}; uint16_t sequence{}; Window affected_window{};
diff --git a/ui/gfx/x/generated_protos/shm.h b/ui/gfx/x/generated_protos/shm.h index 6df3185d..ee89c04 100644 --- a/ui/gfx/x/generated_protos/shm.h +++ b/ui/gfx/x/generated_protos/shm.h
@@ -85,7 +85,6 @@ struct CompletionEvent { static constexpr int type_id = 15; static constexpr uint8_t opcode = 0; - bool send_event{}; uint16_t sequence{}; Drawable drawable{}; uint16_t minor_event{};
diff --git a/ui/gfx/x/generated_protos/sync.cc b/ui/gfx/x/generated_protos/sync.cc index f175c29b..7c4c3c28 100644 --- a/ui/gfx/x/generated_protos/sync.cc +++ b/ui/gfx/x/generated_protos/sync.cc
@@ -40,6 +40,7 @@ #include "sync.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/sync.h b/ui/gfx/x/generated_protos/sync.h index 85ef3d1..b215bba 100644 --- a/ui/gfx/x/generated_protos/sync.h +++ b/ui/gfx/x/generated_protos/sync.h
@@ -157,7 +157,6 @@ struct CounterNotifyEvent { static constexpr int type_id = 16; static constexpr uint8_t opcode = 0; - bool send_event{}; uint8_t kind{}; uint16_t sequence{}; Counter counter{}; @@ -173,7 +172,6 @@ struct AlarmNotifyEvent { static constexpr int type_id = 17; static constexpr uint8_t opcode = 1; - bool send_event{}; uint8_t kind{}; uint16_t sequence{}; Alarm alarm{};
diff --git a/ui/gfx/x/generated_protos/xc_misc.cc b/ui/gfx/x/generated_protos/xc_misc.cc index e75c0a82..3a5ccd2e 100644 --- a/ui/gfx/x/generated_protos/xc_misc.cc +++ b/ui/gfx/x/generated_protos/xc_misc.cc
@@ -40,6 +40,7 @@ #include "xc_misc.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xevie.cc b/ui/gfx/x/generated_protos/xevie.cc index 8eeb44d..7f0dfb14 100644 --- a/ui/gfx/x/generated_protos/xevie.cc +++ b/ui/gfx/x/generated_protos/xevie.cc
@@ -40,6 +40,7 @@ #include "xevie.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xf86dri.cc b/ui/gfx/x/generated_protos/xf86dri.cc index 4acebbe..0ce7d29 100644 --- a/ui/gfx/x/generated_protos/xf86dri.cc +++ b/ui/gfx/x/generated_protos/xf86dri.cc
@@ -40,6 +40,7 @@ #include "xf86dri.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xf86vidmode.cc b/ui/gfx/x/generated_protos/xf86vidmode.cc index c08c336..509cf8b 100644 --- a/ui/gfx/x/generated_protos/xf86vidmode.cc +++ b/ui/gfx/x/generated_protos/xf86vidmode.cc
@@ -40,6 +40,7 @@ #include "xf86vidmode.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xfixes.cc b/ui/gfx/x/generated_protos/xfixes.cc index 88cc351..e3b44e6 100644 --- a/ui/gfx/x/generated_protos/xfixes.cc +++ b/ui/gfx/x/generated_protos/xfixes.cc
@@ -40,6 +40,7 @@ #include "xfixes.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xfixes.h b/ui/gfx/x/generated_protos/xfixes.h index b880acd..75385d0 100644 --- a/ui/gfx/x/generated_protos/xfixes.h +++ b/ui/gfx/x/generated_protos/xfixes.h
@@ -133,7 +133,6 @@ struct SelectionNotifyEvent { static constexpr int type_id = 18; static constexpr uint8_t opcode = 0; - bool send_event{}; SelectionEvent subtype{}; uint16_t sequence{}; Window window{}; @@ -148,7 +147,6 @@ struct CursorNotifyEvent { static constexpr int type_id = 19; static constexpr uint8_t opcode = 1; - bool send_event{}; CursorNotify subtype{}; uint16_t sequence{}; Window window{};
diff --git a/ui/gfx/x/generated_protos/xinerama.cc b/ui/gfx/x/generated_protos/xinerama.cc index e184714..76c83fcb4 100644 --- a/ui/gfx/x/generated_protos/xinerama.cc +++ b/ui/gfx/x/generated_protos/xinerama.cc
@@ -40,6 +40,7 @@ #include "xinerama.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xinput.cc b/ui/gfx/x/generated_protos/xinput.cc index f98f5b2..a89a198 100644 --- a/ui/gfx/x/generated_protos/xinput.cc +++ b/ui/gfx/x/generated_protos/xinput.cc
@@ -40,6 +40,7 @@ #include "xinput.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xinput.h b/ui/gfx/x/generated_protos/xinput.h index e522384..55ee7475 100644 --- a/ui/gfx/x/generated_protos/xinput.h +++ b/ui/gfx/x/generated_protos/xinput.h
@@ -1029,7 +1029,6 @@ struct DeviceValuatorEvent { static constexpr int type_id = 20; static constexpr uint8_t opcode = 0; - bool send_event{}; uint8_t device_id{}; uint16_t sequence{}; uint16_t device_state{}; @@ -1051,7 +1050,6 @@ ProximityIn = 8, ProximityOut = 9, } opcode{}; - bool send_event{}; uint8_t detail{}; uint16_t sequence{}; Time time{}; @@ -1075,7 +1073,6 @@ In = 6, Out = 7, } opcode{}; - bool send_event{}; x11::NotifyDetail detail{}; uint16_t sequence{}; Time time{}; @@ -1089,7 +1086,6 @@ struct DeviceStateNotifyEvent { static constexpr int type_id = 23; static constexpr uint8_t opcode = 10; - bool send_event{}; uint8_t device_id{}; uint16_t sequence{}; Time time{}; @@ -1107,7 +1103,6 @@ struct DeviceMappingNotifyEvent { static constexpr int type_id = 24; static constexpr uint8_t opcode = 11; - bool send_event{}; uint8_t device_id{}; uint16_t sequence{}; Mapping request{}; @@ -1121,7 +1116,6 @@ struct ChangeDeviceNotifyEvent { static constexpr int type_id = 25; static constexpr uint8_t opcode = 12; - bool send_event{}; uint8_t device_id{}; uint16_t sequence{}; Time time{}; @@ -1133,7 +1127,6 @@ struct DeviceKeyStateNotifyEvent { static constexpr int type_id = 26; static constexpr uint8_t opcode = 13; - bool send_event{}; uint8_t device_id{}; uint16_t sequence{}; std::array<uint8_t, 28> keys{}; @@ -1144,7 +1137,6 @@ struct DeviceButtonStateNotifyEvent { static constexpr int type_id = 27; static constexpr uint8_t opcode = 14; - bool send_event{}; uint8_t device_id{}; uint16_t sequence{}; std::array<uint8_t, 28> buttons{}; @@ -1155,7 +1147,6 @@ struct DevicePresenceNotifyEvent { static constexpr int type_id = 28; static constexpr uint8_t opcode = 15; - bool send_event{}; uint16_t sequence{}; Time time{}; DeviceChange devchange{}; @@ -1168,7 +1159,6 @@ struct DevicePropertyNotifyEvent { static constexpr int type_id = 29; static constexpr uint8_t opcode = 16; - bool send_event{}; Property state{}; uint16_t sequence{}; Time time{}; @@ -1181,7 +1171,6 @@ struct DeviceChangedEvent { static constexpr int type_id = 30; static constexpr uint8_t opcode = 1; - bool send_event{}; uint16_t sequence{}; DeviceId deviceid{}; Time time{}; @@ -1204,7 +1193,6 @@ TouchUpdate = 19, TouchEnd = 20, } opcode{}; - bool send_event{}; uint16_t sequence{}; DeviceId deviceid{}; Time time{}; @@ -1235,7 +1223,6 @@ FocusIn = 9, FocusOut = 10, } opcode{}; - bool send_event{}; uint16_t sequence{}; DeviceId deviceid{}; Time time{}; @@ -1269,7 +1256,6 @@ struct HierarchyEvent { static constexpr int type_id = 33; static constexpr uint8_t opcode = 11; - bool send_event{}; uint16_t sequence{}; DeviceId deviceid{}; Time time{}; @@ -1282,7 +1268,6 @@ struct PropertyEvent { static constexpr int type_id = 34; static constexpr uint8_t opcode = 12; - bool send_event{}; uint16_t sequence{}; DeviceId deviceid{}; Time time{}; @@ -1304,7 +1289,6 @@ RawTouchUpdate = 23, RawTouchEnd = 24, } opcode{}; - bool send_event{}; uint16_t sequence{}; DeviceId deviceid{}; Time time{}; @@ -1321,7 +1305,6 @@ struct TouchOwnershipEvent { static constexpr int type_id = 36; static constexpr uint8_t opcode = 21; - bool send_event{}; uint16_t sequence{}; DeviceId deviceid{}; Time time{}; @@ -1341,7 +1324,6 @@ Hit = 25, Leave = 26, } opcode{}; - bool send_event{}; uint16_t sequence{}; DeviceId deviceid{}; Time time{};
diff --git a/ui/gfx/x/generated_protos/xkb.cc b/ui/gfx/x/generated_protos/xkb.cc index e623c97..08366a3 100644 --- a/ui/gfx/x/generated_protos/xkb.cc +++ b/ui/gfx/x/generated_protos/xkb.cc
@@ -40,6 +40,7 @@ #include "xkb.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xkb.h b/ui/gfx/x/generated_protos/xkb.h index 7346ca1..d54d16d 100644 --- a/ui/gfx/x/generated_protos/xkb.h +++ b/ui/gfx/x/generated_protos/xkb.h
@@ -935,7 +935,6 @@ struct NewKeyboardNotifyEvent { static constexpr int type_id = 38; static constexpr uint8_t opcode = 0; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{}; @@ -955,7 +954,6 @@ struct MapNotifyEvent { static constexpr int type_id = 39; static constexpr uint8_t opcode = 1; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{}; @@ -986,7 +984,6 @@ struct StateNotifyEvent { static constexpr int type_id = 40; static constexpr uint8_t opcode = 2; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{}; @@ -1017,7 +1014,6 @@ struct ControlsNotifyEvent { static constexpr int type_id = 41; static constexpr uint8_t opcode = 3; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{}; @@ -1037,7 +1033,6 @@ struct IndicatorStateNotifyEvent { static constexpr int type_id = 42; static constexpr uint8_t opcode = 4; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{}; @@ -1051,7 +1046,6 @@ struct IndicatorMapNotifyEvent { static constexpr int type_id = 43; static constexpr uint8_t opcode = 5; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{}; @@ -1065,7 +1059,6 @@ struct NamesNotifyEvent { static constexpr int type_id = 44; static constexpr uint8_t opcode = 6; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{}; @@ -1089,7 +1082,6 @@ struct CompatMapNotifyEvent { static constexpr int type_id = 45; static constexpr uint8_t opcode = 7; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{}; @@ -1105,7 +1097,6 @@ struct BellNotifyEvent { static constexpr int type_id = 46; static constexpr uint8_t opcode = 8; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{}; @@ -1125,7 +1116,6 @@ struct ActionMessageEvent { static constexpr int type_id = 47; static constexpr uint8_t opcode = 9; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{}; @@ -1143,7 +1133,6 @@ struct AccessXNotifyEvent { static constexpr int type_id = 48; static constexpr uint8_t opcode = 10; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{}; @@ -1159,7 +1148,6 @@ struct ExtensionDeviceNotifyEvent { static constexpr int type_id = 49; static constexpr uint8_t opcode = 11; - bool send_event{}; uint8_t xkbType{}; uint16_t sequence{}; Time time{};
diff --git a/ui/gfx/x/generated_protos/xprint.cc b/ui/gfx/x/generated_protos/xprint.cc index e6d6d84..01f586a 100644 --- a/ui/gfx/x/generated_protos/xprint.cc +++ b/ui/gfx/x/generated_protos/xprint.cc
@@ -40,6 +40,7 @@ #include "xprint.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xprint.h b/ui/gfx/x/generated_protos/xprint.h index 0b776ae..8b7db6d 100644 --- a/ui/gfx/x/generated_protos/xprint.h +++ b/ui/gfx/x/generated_protos/xprint.h
@@ -122,7 +122,6 @@ struct NotifyEvent { static constexpr int type_id = 50; static constexpr uint8_t opcode = 0; - bool send_event{}; uint8_t detail{}; uint16_t sequence{}; PContext context{}; @@ -134,7 +133,6 @@ struct AttributNotifyEvent { static constexpr int type_id = 51; static constexpr uint8_t opcode = 1; - bool send_event{}; uint8_t detail{}; uint16_t sequence{}; PContext context{};
diff --git a/ui/gfx/x/generated_protos/xproto.cc b/ui/gfx/x/generated_protos/xproto.cc index 0d8e008..a1b3eda 100644 --- a/ui/gfx/x/generated_protos/xproto.cc +++ b/ui/gfx/x/generated_protos/xproto.cc
@@ -40,6 +40,7 @@ #include "xproto.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xproto.h b/ui/gfx/x/generated_protos/xproto.h index fef95517..b0ad0e12 100644 --- a/ui/gfx/x/generated_protos/xproto.h +++ b/ui/gfx/x/generated_protos/xproto.h
@@ -809,7 +809,6 @@ Press = 2, Release = 3, } opcode{}; - bool send_event{}; KeyCode detail{}; uint16_t sequence{}; Time time{}; @@ -832,7 +831,6 @@ Press = 4, Release = 5, } opcode{}; - bool send_event{}; Button detail{}; uint16_t sequence{}; Time time{}; @@ -852,7 +850,6 @@ struct MotionNotifyEvent { static constexpr int type_id = 54; static constexpr uint8_t opcode = 6; - bool send_event{}; Motion detail{}; uint16_t sequence{}; Time time{}; @@ -875,7 +872,6 @@ EnterNotify = 7, LeaveNotify = 8, } opcode{}; - bool send_event{}; NotifyDetail detail{}; uint16_t sequence{}; Time time{}; @@ -899,7 +895,6 @@ In = 9, Out = 10, } opcode{}; - bool send_event{}; NotifyDetail detail{}; uint16_t sequence{}; Window event{}; @@ -911,7 +906,6 @@ struct KeymapNotifyEvent { static constexpr int type_id = 57; static constexpr uint8_t opcode = 11; - bool send_event{}; std::array<uint8_t, 31> keys{}; x11::Window* GetWindow() { return nullptr; } @@ -920,7 +914,6 @@ struct ExposeEvent { static constexpr int type_id = 58; static constexpr uint8_t opcode = 12; - bool send_event{}; uint16_t sequence{}; Window window{}; uint16_t x{}; @@ -935,7 +928,6 @@ struct GraphicsExposureEvent { static constexpr int type_id = 59; static constexpr uint8_t opcode = 13; - bool send_event{}; uint16_t sequence{}; Drawable drawable{}; uint16_t x{}; @@ -952,7 +944,6 @@ struct NoExposureEvent { static constexpr int type_id = 60; static constexpr uint8_t opcode = 14; - bool send_event{}; uint16_t sequence{}; Drawable drawable{}; uint16_t minor_opcode{}; @@ -964,7 +955,6 @@ struct VisibilityNotifyEvent { static constexpr int type_id = 61; static constexpr uint8_t opcode = 15; - bool send_event{}; uint16_t sequence{}; Window window{}; Visibility state{}; @@ -975,7 +965,6 @@ struct CreateNotifyEvent { static constexpr int type_id = 62; static constexpr uint8_t opcode = 16; - bool send_event{}; uint16_t sequence{}; Window parent{}; Window window{}; @@ -992,7 +981,6 @@ struct DestroyNotifyEvent { static constexpr int type_id = 63; static constexpr uint8_t opcode = 17; - bool send_event{}; uint16_t sequence{}; Window event{}; Window window{}; @@ -1003,7 +991,6 @@ struct UnmapNotifyEvent { static constexpr int type_id = 64; static constexpr uint8_t opcode = 18; - bool send_event{}; uint16_t sequence{}; Window event{}; Window window{}; @@ -1015,7 +1002,6 @@ struct MapNotifyEvent { static constexpr int type_id = 65; static constexpr uint8_t opcode = 19; - bool send_event{}; uint16_t sequence{}; Window event{}; Window window{}; @@ -1027,7 +1013,6 @@ struct MapRequestEvent { static constexpr int type_id = 66; static constexpr uint8_t opcode = 20; - bool send_event{}; uint16_t sequence{}; Window parent{}; Window window{}; @@ -1038,7 +1023,6 @@ struct ReparentNotifyEvent { static constexpr int type_id = 67; static constexpr uint8_t opcode = 21; - bool send_event{}; uint16_t sequence{}; Window event{}; Window window{}; @@ -1053,7 +1037,6 @@ struct ConfigureNotifyEvent { static constexpr int type_id = 68; static constexpr uint8_t opcode = 22; - bool send_event{}; uint16_t sequence{}; Window event{}; Window window{}; @@ -1071,7 +1054,6 @@ struct ConfigureRequestEvent { static constexpr int type_id = 69; static constexpr uint8_t opcode = 23; - bool send_event{}; StackMode stack_mode{}; uint16_t sequence{}; Window parent{}; @@ -1090,7 +1072,6 @@ struct GravityNotifyEvent { static constexpr int type_id = 70; static constexpr uint8_t opcode = 24; - bool send_event{}; uint16_t sequence{}; Window event{}; Window window{}; @@ -1103,7 +1084,6 @@ struct ResizeRequestEvent { static constexpr int type_id = 71; static constexpr uint8_t opcode = 25; - bool send_event{}; uint16_t sequence{}; Window window{}; uint16_t width{}; @@ -1118,7 +1098,6 @@ Notify = 26, Request = 27, } opcode{}; - bool send_event{}; uint16_t sequence{}; Window event{}; Window window{}; @@ -1130,7 +1109,6 @@ struct PropertyNotifyEvent { static constexpr int type_id = 73; static constexpr uint8_t opcode = 28; - bool send_event{}; uint16_t sequence{}; Window window{}; Atom atom{}; @@ -1143,7 +1121,6 @@ struct SelectionClearEvent { static constexpr int type_id = 74; static constexpr uint8_t opcode = 29; - bool send_event{}; uint16_t sequence{}; Time time{}; Window owner{}; @@ -1155,7 +1132,6 @@ struct SelectionRequestEvent { static constexpr int type_id = 75; static constexpr uint8_t opcode = 30; - bool send_event{}; uint16_t sequence{}; Time time{}; Window owner{}; @@ -1170,7 +1146,6 @@ struct SelectionNotifyEvent { static constexpr int type_id = 76; static constexpr uint8_t opcode = 31; - bool send_event{}; uint16_t sequence{}; Time time{}; Window requestor{}; @@ -1186,7 +1161,6 @@ struct ColormapNotifyEvent { static constexpr int type_id = 77; static constexpr uint8_t opcode = 32; - bool send_event{}; uint16_t sequence{}; Window window{}; ColorMap colormap{}; @@ -1208,7 +1182,6 @@ struct ClientMessageEvent { static constexpr int type_id = 78; static constexpr uint8_t opcode = 33; - bool send_event{}; uint8_t format{}; uint16_t sequence{}; Window window{}; @@ -1221,7 +1194,6 @@ struct MappingNotifyEvent { static constexpr int type_id = 79; static constexpr uint8_t opcode = 34; - bool send_event{}; uint16_t sequence{}; Mapping request{}; KeyCode first_keycode{}; @@ -1233,7 +1205,6 @@ struct GeGenericEvent { static constexpr int type_id = 80; static constexpr uint8_t opcode = 35; - bool send_event{}; uint16_t sequence{}; x11::Window* GetWindow() { return nullptr; }
diff --git a/ui/gfx/x/generated_protos/xselinux.cc b/ui/gfx/x/generated_protos/xselinux.cc index 453b3de..8f2dffb 100644 --- a/ui/gfx/x/generated_protos/xselinux.cc +++ b/ui/gfx/x/generated_protos/xselinux.cc
@@ -40,6 +40,7 @@ #include "xselinux.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xtest.cc b/ui/gfx/x/generated_protos/xtest.cc index 709caef..14298ac2 100644 --- a/ui/gfx/x/generated_protos/xtest.cc +++ b/ui/gfx/x/generated_protos/xtest.cc
@@ -40,6 +40,7 @@ #include "xtest.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xv.cc b/ui/gfx/x/generated_protos/xv.cc index 0171ced3..c206f2d 100644 --- a/ui/gfx/x/generated_protos/xv.cc +++ b/ui/gfx/x/generated_protos/xv.cc
@@ -40,6 +40,7 @@ #include "xv.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gfx/x/generated_protos/xv.h b/ui/gfx/x/generated_protos/xv.h index c4a89f32..f874a61 100644 --- a/ui/gfx/x/generated_protos/xv.h +++ b/ui/gfx/x/generated_protos/xv.h
@@ -218,7 +218,6 @@ struct VideoNotifyEvent { static constexpr int type_id = 81; static constexpr uint8_t opcode = 0; - bool send_event{}; VideoNotifyReason reason{}; uint16_t sequence{}; Time time{}; @@ -233,7 +232,6 @@ struct PortNotifyEvent { static constexpr int type_id = 82; static constexpr uint8_t opcode = 1; - bool send_event{}; uint16_t sequence{}; Time time{}; Port port{};
diff --git a/ui/gfx/x/generated_protos/xvmc.cc b/ui/gfx/x/generated_protos/xvmc.cc index 98fbbb5e..30e35505 100644 --- a/ui/gfx/x/generated_protos/xvmc.cc +++ b/ui/gfx/x/generated_protos/xvmc.cc
@@ -40,6 +40,7 @@ #include "xvmc.h" +#include <unistd.h> #include <xcb/xcb.h> #include <xcb/xcbext.h>
diff --git a/ui/gtk/x/gtk_event_loop_x11.cc b/ui/gtk/x/gtk_event_loop_x11.cc index b259260e..c7a8f91 100644 --- a/ui/gtk/x/gtk_event_loop_x11.cc +++ b/ui/gtk/x/gtk_event_loop_x11.cc
@@ -20,14 +20,13 @@ return static_cast<x11::KeyButMask>(state | ((group & 0x3) << 13)); } -x11::KeyEvent ConvertGdkEventToKeyEvent(GdkEvent* gdk_event) { +x11::Event ConvertGdkEventToKeyEvent(GdkEvent* gdk_event) { if (!gtk::GtkCheckVersion(4)) { auto* key = reinterpret_cast<GdkEventKey*>(gdk_event); DCHECK(key->type == GdkKeyPress() || key->type == GdkKeyRelease()); - return { + x11::KeyEvent key_event{ .opcode = key->type == GdkKeyPress() ? x11::KeyEvent::Press : x11::KeyEvent::Release, - .send_event = !!key->send_event, .detail = static_cast<x11::KeyCode>(key->hardware_keycode), .time = static_cast<x11::Time>(key->time), .root = ui::GetX11RootWindow(), @@ -35,6 +34,7 @@ .state = BuildXkbStateFromGdkEvent(key->state, key->group), .same_screen = true, }; + return x11::Event(!!key->send_event, std::move(key_event)); } GdkKeymapKey* keys = nullptr; @@ -56,7 +56,7 @@ g_free(keyvals); } - return { + x11::KeyEvent key_event{ .opcode = gtk::GdkEventGetEventType(gdk_event) == GdkKeyPress() ? x11::KeyEvent::Press : x11::KeyEvent::Release, @@ -69,6 +69,7 @@ gdk_event_get_modifier_state(gdk_event), keymap_key.group), .same_screen = true, }; + return x11::Event(false, std::move(key_event)); } void ProcessGdkEvent(GdkEvent* gdk_event) { @@ -94,8 +95,7 @@ // We want to process the gtk event; mapped to an X11 event immediately // otherwise if we put it back on the queue we may get items out of order. - x11::Connection::Get()->DispatchEvent( - x11::Event{ConvertGdkEventToKeyEvent(gdk_event)}); + x11::Connection::Get()->DispatchEvent(ConvertGdkEventToKeyEvent(gdk_event)); } } // namespace
diff --git a/ui/ozone/platform/wayland/host/wayland_frame_manager.cc b/ui/ozone/platform/wayland/host/wayland_frame_manager.cc index 083e23c..9a20d973 100644 --- a/ui/ozone/platform/wayland/host/wayland_frame_manager.cc +++ b/ui/ozone/platform/wayland/host/wayland_frame_manager.cc
@@ -213,8 +213,8 @@ } if (empty_frame) { - root_surface->AttachBuffer(nullptr); - root_surface->ApplyPendingState(); + // GPU channel has been destroyed. Do nothing for empty frames except that + // the frame should be marked as failed if it hasn't been presented yet. if (!frame->presentation_acked) frame->feedback = gfx::PresentationFeedback::Failure(); } else {
diff --git a/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc b/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc index 71ac713b..87d7814b 100644 --- a/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc +++ b/ui/ozone/platform/wayland/wayland_buffer_manager_unittest.cc
@@ -1941,8 +1941,8 @@ bounds); Sync(); - // Null buffer shall be attached when channel is destroyed. - EXPECT_CALL(*mock_surface, Attach(nullptr, _, _)).Times(1); + // The root surface shouldn't get null buffer attached. + EXPECT_CALL(*mock_surface, Attach(_, _, _)).Times(0); EXPECT_CALL(*mock_surface, Commit()).Times(1); mock_surface->SendFrameCallback(); @@ -2067,10 +2067,9 @@ Sync(); - // The root surface should not have the buffer detached. - EXPECT_FALSE(mock_surface->attached_buffer()); - - // The primary and secondary subsurfaces must be hidden. + // The root surface should still have the buffer attached.... + EXPECT_TRUE(mock_surface->attached_buffer()); + // ... and the primary and secondary subsurfaces must be hidden. EXPECT_FALSE(window_->primary_subsurface()->IsVisible()); EXPECT_EQ(1u, window_->wayland_subsurfaces().size()); EXPECT_FALSE(window_->wayland_subsurfaces().begin()->get()->IsVisible());
diff --git a/ui/ozone/platform/x11/test/events_x_unittest.cc b/ui/ozone/platform/x11/test/events_x_unittest.cc index 82a4db94..8696420 100644 --- a/ui/ozone/platform/x11/test/events_x_unittest.cc +++ b/ui/ozone/platform/x11/test/events_x_unittest.cc
@@ -44,13 +44,14 @@ const gfx::Point& location, int button, x11::KeyButMask state) { - *event = x11::Event(x11::ButtonEvent{ - .opcode = is_press ? x11::ButtonEvent::Press : x11::ButtonEvent::Release, - .detail = static_cast<x11::Button>(button), - .event_x = static_cast<int16_t>(location.x()), - .event_y = static_cast<int16_t>(location.y()), - .state = state, - }); + *event = x11::Event(false, x11::ButtonEvent{ + .opcode = is_press ? x11::ButtonEvent::Press + : x11::ButtonEvent::Release, + .detail = static_cast<x11::Button>(button), + .event_x = static_cast<int16_t>(location.x()), + .event_y = static_cast<int16_t>(location.y()), + .state = state, + }); } #if !BUILDFLAG(IS_CHROMEOS_ASH) @@ -61,11 +62,12 @@ x11::KeyButMask state) { // We don't bother setting fields that the event code doesn't use, such as // x_root/y_root and window/root/subwindow. - *event = x11::Event(x11::KeyEvent{ - .opcode = is_press ? x11::KeyEvent::Press : x11::KeyEvent::Release, - .detail = static_cast<x11::KeyCode>(keycode), - .state = state, - }); + *event = x11::Event(false, x11::KeyEvent{ + .opcode = is_press ? x11::KeyEvent::Press + : x11::KeyEvent::Release, + .detail = static_cast<x11::KeyCode>(keycode), + .state = state, + }); } #endif @@ -190,13 +192,13 @@ } TEST_F(EventsXTest, EnterLeaveEvent) { - x11::Event event(x11::CrossingEvent{ - .opcode = x11::CrossingEvent::EnterNotify, - .root_x = 110, - .root_y = 120, - .event_x = 10, - .event_y = 20, - }); + x11::Event event(false, x11::CrossingEvent{ + .opcode = x11::CrossingEvent::EnterNotify, + .root_x = 110, + .root_y = 120, + .event_x = 10, + .event_y = 20, + }); // Mouse enter events are converted to mouse move events to be consistent with // the way views handle mouse enter. See comments for EnterNotify case in @@ -206,13 +208,13 @@ EXPECT_EQ("10,20", ui::EventLocationFromXEvent(event).ToString()); EXPECT_EQ("110,120", ui::EventSystemLocationFromXEvent(event).ToString()); - event = x11::Event(x11::CrossingEvent{ - .opcode = x11::CrossingEvent::LeaveNotify, - .root_x = 230, - .root_y = 240, - .event_x = 30, - .event_y = 40, - }); + event = x11::Event(false, x11::CrossingEvent{ + .opcode = x11::CrossingEvent::LeaveNotify, + .root_x = 230, + .root_y = 240, + .event_x = 30, + .event_y = 40, + }); EXPECT_EQ(ui::ET_MOUSE_EXITED, ui::EventTypeFromXEvent(event)); EXPECT_EQ("30,40", ui::EventLocationFromXEvent(event).ToString()); EXPECT_EQ("230,240", ui::EventSystemLocationFromXEvent(event).ToString()); @@ -800,11 +802,12 @@ DeviceDataManagerX11::CreateInstance(); // Initializes a native event and uses it to generate a MouseWheel event. - x11::Event native_event(x11::ButtonEvent{ - .opcode = x11::ButtonEvent::Press, - // A valid wheel button number between min and max. - .detail = static_cast<x11::Button>(4), - }); + x11::Event native_event( + false, x11::ButtonEvent{ + .opcode = x11::ButtonEvent::Press, + // A valid wheel button number between min and max. + .detail = static_cast<x11::Button>(4), + }); auto mouse_ev = ui::BuildMouseWheelEventFromXEvent(native_event); histogram_tester.ExpectTotalCount("Event.Latency.OS.MOUSE_WHEEL", 1); histogram_tester.ExpectTotalCount("Event.Latency.OS2.MOUSE_WHEEL", 1);
diff --git a/ui/ozone/platform/x11/test/x11_event_translation_unittest.cc b/ui/ozone/platform/x11/test/x11_event_translation_unittest.cc index 72164a2..809fcd54 100644 --- a/ui/ozone/platform/x11/test/x11_event_translation_unittest.cc +++ b/ui/ozone/platform/x11/test/x11_event_translation_unittest.cc
@@ -179,10 +179,10 @@ EXPECT_EQ(0, mouseev2->changed_button_flags()); // Taking in a EnterNotify XEvent - x11::Event enter_event(x11::CrossingEvent{ - .opcode = x11::CrossingEvent::EnterNotify, - .detail = x11::NotifyDetail::Virtual, - }); + x11::Event enter_event(false, x11::CrossingEvent{ + .opcode = x11::CrossingEvent::EnterNotify, + .detail = x11::NotifyDetail::Virtual, + }); auto mouseev3 = ui::BuildMouseEventFromXEvent(enter_event); EXPECT_TRUE(mouseev3);
diff --git a/ui/ozone/platform/x11/test/x11_window_unittest.cc b/ui/ozone/platform/x11/test/x11_window_unittest.cc index 1f50dff..f6e41d42b 100644 --- a/ui/ozone/platform/x11/test/x11_window_unittest.cc +++ b/ui/ozone/platform/x11/test/x11_window_unittest.cc
@@ -456,9 +456,11 @@ EXPECT_EQ(initial_bounds, window->GetBounds()); } +// TODO(crbug.com/1294066): Flaky on both Linux and ChromeOS. // Tests that the minimization information is propagated to the // PlatformWindowDelegate. -TEST_F(X11WindowTest, ToggleMinimizePropogateToPlatformWindowDelegate) { +TEST_F(X11WindowTest, + DISABLED_ToggleMinimizePropogateToPlatformWindowDelegate) { TestPlatformWindowDelegate delegate; constexpr gfx::Rect bounds(10, 10, 100, 100); auto window = CreateX11Window(&delegate, bounds, nullptr);
diff --git a/ui/ozone/platform/x11/x11_window.cc b/ui/ozone/platform/x11/x11_window.cc index 9b15b6e0..15b5f6f 100644 --- a/ui/ozone/platform/x11/x11_window.cc +++ b/ui/ozone/platform/x11/x11_window.cc
@@ -2086,7 +2086,7 @@ OnFocusEvent(focus->opcode == x11::FocusEvent::In, focus->mode, focus->detail); } else if (auto* configure = xev.As<x11::ConfigureNotifyEvent>()) { - OnConfigureEvent(*configure); + OnConfigureEvent(*configure, xev.send_event()); } else if (auto* crossing_input = xev.As<x11::Input::CrossingEvent>()) { TouchFactory* factory = TouchFactory::GetInstance(); if (factory->ShouldProcessCrossingEvent(*crossing_input)) { @@ -2182,7 +2182,8 @@ } } -void X11Window::OnConfigureEvent(const x11::ConfigureNotifyEvent& configure) { +void X11Window::OnConfigureEvent(const x11::ConfigureNotifyEvent& configure, + bool send_event) { DCHECK_EQ(xwindow_, configure.window); DCHECK_EQ(xwindow_, configure.event); @@ -2208,7 +2209,7 @@ // sure the root window size is maintained properly. int translated_x_in_pixels = configure.x; int translated_y_in_pixels = configure.y; - if (!configure.send_event && !configure.override_redirect) { + if (!send_event && !configure.override_redirect) { auto future = connection_->TranslateCoordinates({xwindow_, x_root_window_, 0, 0}); if (auto coords = future.Sync()) {
diff --git a/ui/ozone/platform/x11/x11_window.h b/ui/ozone/platform/x11/x11_window.h index 98cf55a..0b4ccfe 100644 --- a/ui/ozone/platform/x11/x11_window.h +++ b/ui/ozone/platform/x11/x11_window.h
@@ -267,7 +267,8 @@ // Called when |xwindow_|'s _NET_FRAME_EXTENTS property is updated. void OnFrameExtentsUpdated(); - void OnConfigureEvent(const x11::ConfigureNotifyEvent& event); + void OnConfigureEvent(const x11::ConfigureNotifyEvent& event, + bool send_event); void OnWorkspaceUpdated();
diff --git a/ui/views/interaction/element_tracker_views.cc b/ui/views/interaction/element_tracker_views.cc index f9348963..5d9c547 100644 --- a/ui/views/interaction/element_tracker_views.cc +++ b/ui/views/interaction/element_tracker_views.cc
@@ -290,6 +290,17 @@ return it->second.GetAllViews(); } +bool ElementTrackerViews::NotifyCustomEvent( + ui::CustomElementEventType event_type, + View* view) { + auto* const element = GetElementForView(view, /* assign_temporary_id =*/true); + if (!element) + return false; + ui::ElementTracker::GetFrameworkDelegate()->NotifyCustomEvent(element, + event_type); + return true; +} + void ElementTrackerViews::RegisterView(ui::ElementIdentifier element_id, View* view) { const auto [it, added] =
diff --git a/ui/views/interaction/element_tracker_views.h b/ui/views/interaction/element_tracker_views.h index 21ce0d09..c770e8c 100644 --- a/ui/views/interaction/element_tracker_views.h +++ b/ui/views/interaction/element_tracker_views.h
@@ -101,6 +101,12 @@ // identifier. ViewList GetAllMatchingViewsInAnyContext(ui::ElementIdentifier id); + // Notifies listeners that a specific custom event has occurred for the given + // view. Calls GetElementForView(view, true) under the hood; returns false if + // an element cannot be found or created for the view (e.g. in the case where + // it is not visible or associated with a widget). + bool NotifyCustomEvent(ui::CustomElementEventType event_type, View* view); + // ---------- // The following methods are used by View and derived classes to send events // to ElementTracker. ElementTrackerViews maintains additional observers and
diff --git a/ui/views/interaction/element_tracker_views_unittest.cc b/ui/views/interaction/element_tracker_views_unittest.cc index 1386e91..ba1228e 100644 --- a/ui/views/interaction/element_tracker_views_unittest.cc +++ b/ui/views/interaction/element_tracker_views_unittest.cc
@@ -31,10 +31,12 @@ DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestElementID); DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestElementID2); +DECLARE_CUSTOM_ELEMENT_EVENT_TYPE(kCustomEventType); +DEFINE_CUSTOM_ELEMENT_EVENT_TYPE(kCustomEventType); namespace { -enum ElementEventType { kShown, kActivated, kHidden }; +enum ElementEventType { kShown, kActivated, kHidden, kCustom }; View* ElementToView(ui::TrackedElement* element) { auto* const view_element = element->AsA<TrackedElementViews>(); @@ -54,11 +56,11 @@ ElementEventWatcher(ui::ElementIdentifier id, ui::ElementContext context, ElementEventType event_type) - : id_(id) { + : id_(id), event_type_(event_type) { auto callback = base::BindRepeating(&ElementEventWatcher::OnEvent, base::Unretained(this)); ui::ElementTracker* const tracker = ui::ElementTracker::GetElementTracker(); - switch (event_type) { + switch (event_type_) { case ElementEventType::kShown: subscription_ = tracker->AddElementShownCallback(id, context, callback); break; @@ -70,6 +72,9 @@ subscription_ = tracker->AddElementHiddenCallback(id, context, callback); break; + case ElementEventType::kCustom: + subscription_ = tracker->AddCustomEventCallback(id, context, callback); + break; } } @@ -78,12 +83,14 @@ private: void OnEvent(ui::TrackedElement* element) { - EXPECT_EQ(id_, element->identifier()); + if (event_type_ != ElementEventType::kCustom) + EXPECT_EQ(id_, element->identifier()); last_view_ = ElementToView(element); ++event_count_; } const ui::ElementIdentifier id_; + const ElementEventType event_type_; ui::ElementTracker::Subscription subscription_; int event_count_ = 0; raw_ptr<View> last_view_ = nullptr; @@ -297,6 +304,47 @@ EXPECT_EQ(button, watcher.last_view()); } +TEST_F(ElementTrackerViewsTest, SendCustomEventWithNamedElement) { + ElementEventWatcher watcher(kCustomEventType, context(), + ElementEventType::kCustom); + auto* const target = widget_->SetContentsView(std::make_unique<View>()); + target->SetProperty(kElementIdentifierKey, kTestElementID); + EXPECT_EQ(0, watcher.event_count()); + ElementTrackerViews::GetInstance()->NotifyCustomEvent(kCustomEventType, + target); + EXPECT_EQ(1, watcher.event_count()); + EXPECT_EQ(target, watcher.last_view()); + // Send an event with a different ID (which happens to be the element's ID; + // this shouldn't happen but we should handle it gracefully). + ElementTrackerViews::GetInstance()->NotifyCustomEvent(kTestElementID, target); + EXPECT_EQ(1, watcher.event_count()); + // Send another event. + ElementTrackerViews::GetInstance()->NotifyCustomEvent(kCustomEventType, + target); + EXPECT_EQ(2, watcher.event_count()); + EXPECT_EQ(target, watcher.last_view()); +} + +TEST_F(ElementTrackerViewsTest, SendCustomEventWithUnnamedElement) { + ElementEventWatcher watcher(kCustomEventType, context(), + ElementEventType::kCustom); + auto* const target = widget_->SetContentsView(std::make_unique<View>()); + // View has no pre-set identifier, but this should still work. + EXPECT_EQ(0, watcher.event_count()); + ElementTrackerViews::GetInstance()->NotifyCustomEvent(kCustomEventType, + target); + EXPECT_EQ(1, watcher.event_count()); + EXPECT_EQ(target, watcher.last_view()); + // Send an extraneous event. + ElementTrackerViews::GetInstance()->NotifyCustomEvent(kTestElementID, target); + EXPECT_EQ(1, watcher.event_count()); + // Send another event. + ElementTrackerViews::GetInstance()->NotifyCustomEvent(kCustomEventType, + target); + EXPECT_EQ(2, watcher.event_count()); + EXPECT_EQ(target, watcher.last_view()); +} + TEST_F(ElementTrackerViewsTest, HandlesCreateWithTheSameIDMultipleTimes) { ElementEventWatcher watcher(kTestElementID, context(), ElementEventType::kShown);
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc index 7e803d5..b5ae1873 100644 --- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc +++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -528,6 +528,7 @@ void DesktopNativeWidgetAura::InitNativeWidget(Widget::InitParams params) { ownership_ = params.ownership; widget_type_ = params.type; + headless_mode_ = params.headless_mode; name_ = params.name; content_window_->AcquireAllPropertiesFrom( @@ -877,7 +878,10 @@ const gfx::Rect& restore_bounds) { if (!content_window_) return; - desktop_window_tree_host_->Show(show_state, restore_bounds); + // Avoid changing desktop window visibility state when browser is running in + // headless mode, see https://crbug.com/1237546. + if (!headless_mode_) + desktop_window_tree_host_->Show(show_state, restore_bounds); } void DesktopNativeWidgetAura::Hide() {
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h index c1b4ff3..6f8e23c 100644 --- a/ui/views/widget/desktop_aura/desktop_native_widget_aura.h +++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -343,6 +343,9 @@ // See class documentation for Widget in widget.h for a note about type. Widget::InitParams::Type widget_type_; + // Set if the desktop window was created in headless mode. + bool headless_mode_ = false; + // See DesktopWindowTreeHost::ShouldUseDesktopNativeCursorManager(). bool use_desktop_native_cursor_manager_ = false;
diff --git a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_utils.js b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_utils.js index 65369bc..c4660ab 100644 --- a/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_utils.js +++ b/ui/webui/resources/cr_components/chromeos/bluetooth/bluetooth_utils.js
@@ -107,3 +107,31 @@ getBatteryPercentage(device, BatteryType.CASE) !== undefined || getBatteryPercentage(device, BatteryType.RIGHT_BUD) !== undefined; } + +/** + * Returns true if the device contains True Wireless Images. + * @param {!chromeos.bluetoothConfig.mojom.BluetoothDeviceProperties} + * device + * @return {boolean} + */ +export function hasTrueWirelessImages(device) { + const imageInfo = device.imageInfo; + if (!imageInfo) { + return false; + } + + const trueWirelessImages = imageInfo.trueWirelessImages; + if (!trueWirelessImages) { + return false; + } + + // Only return true if all True Wireless Images are present. + const leftBudImageUrl = trueWirelessImages.leftBudImageUrl; + const rightBudImageUrl = trueWirelessImages.rightBudImageUrl; + const caseImageUrl = trueWirelessImages.caseImageUrl; + if (!leftBudImageUrl || !rightBudImageUrl || !caseImageUrl) { + return false; + } + + return !!leftBudImageUrl.url && !!rightBudImageUrl.url && !!caseImageUrl.url; +}
diff --git a/ui/webui/resources/cr_elements/md_select_css.html b/ui/webui/resources/cr_elements/md_select_css.html index 6ce0769..a5c641b 100644 --- a/ui/webui/resources/cr_elements/md_select_css.html +++ b/ui/webui/resources/cr_elements/md_select_css.html
@@ -12,7 +12,7 @@ --md-select-focus-shadow-color: rgba(var(--google-blue-600-rgb), .4); --md-select-option-bg-color: white; --md-select-side-padding: 8px; - --md-select-text-color: var(--google-grey-900); + --md-select-text-color: var(--cr-primary-text-color); -webkit-appearance: none; background: url(chrome://resources/images/arrow_down.svg) @@ -44,7 +44,6 @@ --md-select-focus-shadow-color: rgba(var(--google-blue-300-rgb), .5); --md-select-option-bg-color: var(--google-grey-900-white-4-percent); - --md-select-text-color: var(--cr-primary-text-color); background-image: url(chrome://resources/images/dark/arrow_down.svg); } }
diff --git a/url/android/test/java/src/org/chromium/url/JUnitTestGURLs.java b/url/android/test/java/src/org/chromium/url/JUnitTestGURLs.java index 1b64d39..d00536b 100644 --- a/url/android/test/java/src/org/chromium/url/JUnitTestGURLs.java +++ b/url/android/test/java/src/org/chromium/url/JUnitTestGURLs.java
@@ -50,6 +50,7 @@ public static final String TEXT_FRAGMENT_URL = "https://www.example.com/#:~:text=selector"; public static final String MULTI_TEXT_FRAGMENT_URL = "https://www.example.com/#:~:text=selector1&text=selector2&text=selector3"; + public static final String INVALID_URL = "http://0x100.0/"; // Map of URL string to GURL serialization. /* package */ static final Map<String, String> sGURLMap; @@ -121,6 +122,8 @@ "100,1,true,0,5,0,-1,0,-1,8,15,0,-1,23,1,0,-1,25,16,false,false,https://www.example.com/#:~:text=selector"); map.put(MULTI_TEXT_FRAGMENT_URL, "131,1,true,0,5,0,-1,0,-1,8,15,0,-1,23,1,0,-1,25,47,false,false,https://www.example.com/#:~:text=selector1&text=selector2&text=selector3"); + map.put(INVALID_URL, + "73,1,false,0,4,0,-1,0,-1,7,7,0,-1,14,1,0,-1,0,-1,false,false,http://0x100.0/"); sGURLMap = Collections.unmodifiableMap(map); }
diff --git a/weblayer/browser/content_browser_client_impl.cc b/weblayer/browser/content_browser_client_impl.cc index d7ec930..1128296 100644 --- a/weblayer/browser/content_browser_client_impl.cc +++ b/weblayer/browser/content_browser_client_impl.cc
@@ -427,6 +427,10 @@ return embedder_support::GetUserAgent(); } +std::string ContentBrowserClientImpl::GetFullUserAgent() { + return embedder_support::GetFullUserAgent(); +} + std::string ContentBrowserClientImpl::GetReducedUserAgent() { return embedder_support::GetReducedUserAgent(); }
diff --git a/weblayer/browser/content_browser_client_impl.h b/weblayer/browser/content_browser_client_impl.h index 3f28f4df..b414962 100644 --- a/weblayer/browser/content_browser_client_impl.h +++ b/weblayer/browser/content_browser_client_impl.h
@@ -94,6 +94,7 @@ blink::mojom::WebFeature feature) override; std::string GetProduct() override; std::string GetUserAgent() override; + std::string GetFullUserAgent() override; std::string GetReducedUserAgent() override; blink::UserAgentMetadata GetUserAgentMetadata() override; void OverrideWebkitPrefs(content::WebContents* web_contents,
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java index 037dcac..c5d1d17 100644 --- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java +++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
@@ -4,6 +4,7 @@ package org.chromium.weblayer_private; +import android.annotation.SuppressLint; import android.app.Service; import android.content.Context; import android.content.Intent; @@ -103,6 +104,7 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Constructor; +import java.lang.reflect.Field; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; @@ -935,10 +937,22 @@ } } + @SuppressLint("DiscouragedPrivateApi") private static Context createContextForMode(Context remoteContext, int uiMode) { Configuration configuration = new Configuration(); configuration.uiMode = uiMode; - return remoteContext.createConfigurationContext(configuration); + Context context = remoteContext.createConfigurationContext(configuration); + // DrawableInflater uses the ClassLoader from the Resources object. We need to make sure + // this ClassLoader is correct. See crbug.com/1287000 and crbug.com/1293849 for more + // details. + try { + Field classLoaderField = Resources.class.getDeclaredField("mClassLoader"); + classLoaderField.setAccessible(true); + classLoaderField.set(context.getResources(), WebLayerImpl.class.getClassLoader()); + } catch (ReflectiveOperationException e) { + Log.e(TAG, "Error setting Resources ClassLoader.", e); + } + return context; } @CalledByNative
diff --git a/weblayer/renderer/content_renderer_client_impl.cc b/weblayer/renderer/content_renderer_client_impl.cc index 775b30d..b570371 100644 --- a/weblayer/renderer/content_renderer_client_impl.cc +++ b/weblayer/renderer/content_renderer_client_impl.cc
@@ -215,12 +215,14 @@ browser_interface_broker_.get(), provider_type); } -void ContentRendererClientImpl::AddSupportedKeySystems( - std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) { +void ContentRendererClientImpl::GetSupportedKeySystems( + media::GetSupportedKeySystemsCB cb) { + media::KeySystemPropertiesVector key_systems; #if BUILDFLAG(IS_ANDROID) - cdm::AddAndroidWidevine(key_systems); - cdm::AddAndroidPlatformKeySystems(key_systems); + cdm::AddAndroidWidevine(&key_systems); + cdm::AddAndroidPlatformKeySystems(&key_systems); #endif + std::move(cb).Run(std::move(key_systems)); } void ContentRendererClientImpl::
diff --git a/weblayer/renderer/content_renderer_client_impl.h b/weblayer/renderer/content_renderer_client_impl.h index 805e228..c5318ec 100644 --- a/weblayer/renderer/content_renderer_client_impl.h +++ b/weblayer/renderer/content_renderer_client_impl.h
@@ -48,9 +48,7 @@ std::unique_ptr<blink::URLLoaderThrottleProvider> CreateURLLoaderThrottleProvider( blink::URLLoaderThrottleProviderType provider_type) override; - void AddSupportedKeySystems( - std::vector<std::unique_ptr<::media::KeySystemProperties>>* key_systems) - override; + void GetSupportedKeySystems(media::GetSupportedKeySystemsCB cb) override; void SetRuntimeFeaturesDefaultsBeforeBlinkInitialization() override; bool IsPrefetchOnly(content::RenderFrame* render_frame) override; bool DeferMediaLoad(content::RenderFrame* render_frame,