diff --git a/DEPS b/DEPS index 92005a0..34b1fbf 100644 --- a/DEPS +++ b/DEPS
@@ -129,11 +129,11 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling Skia # and whatever else without interference from each other. - 'skia_revision': '7340124746df2f1ce25e0aaa134ee370d0ebffee', + 'skia_revision': 'aba7a5c93b91ee49c8a281daf19e8715978b7d81', # 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': '72592828213b06ab2f4b69f2ed5685c1e43123b1', + 'v8_revision': 'a3c1051c26e72b7b86bd93d580e4a39ebdcbecd2', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling swarming_client # and whatever else without interference from each other. @@ -141,15 +141,15 @@ # 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': '5f388c24529334c694e245be69226581a01d1622', + 'angle_revision': '90b1865e2a8b644bc3e200726de9e3a321ee5c18', # 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': '60da1580366f44667980c4402b53cd00097f9443', + 'swiftshader_revision': '4ba1911b2d7f526695ffed525faa9c903cd6737b', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. - 'pdfium_revision': '7e4877f634e4e4db77ec1a26974cd314a2f004db', + 'pdfium_revision': '3419af426bd572e23f3e8b0ab994589e3e4020af', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling openmax_dl # and whatever else without interference from each other. @@ -180,7 +180,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling NaCl # and whatever else without interference from each other. - 'nacl_revision': '2c300847c7700af6948ad78e79ccd21bd7ba0c14', + 'nacl_revision': '067afa275dcb4b3c6eca979ea5e3fe75073c4080', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. @@ -196,7 +196,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': 'bf0179e27c9fafbf52a6ec6e771d89a9d81a5f47', + 'catapult_revision': '979fc35bbcca4c9015176a71d8d71abe023d94e8', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -805,7 +805,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'bd047d05d120039e5820795e2c7b6b5b1f3873e3', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'd5f1da86cc3a55856e1d259b941c2c7f967e12cf', 'condition': 'checkout_linux', }, @@ -830,7 +830,7 @@ }, 'src/third_party/depot_tools': - Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '9198ef8ede661f96912f5f226d566ae1f1998f7b', + Var('chromium_git') + '/chromium/tools/depot_tools.git' + '@' + '0b62ed79ed5049332f58c06dbdb8e8bc4105010e', 'src/third_party/devtools-node-modules': Var('chromium_git') + '/external/github.com/ChromeDevTools/devtools-node-modules' + '@' + Var('devtools_node_modules_revision'), @@ -1172,7 +1172,7 @@ }, 'src/third_party/perfetto': - Var('android_git') + '/platform/external/perfetto.git' + '@' + 'cc57bf714a300c5e0b6bc04f76ea058e50c38399', + Var('android_git') + '/platform/external/perfetto.git' + '@' + '766ef6cc7749a612c271720bf04f545d0e8a57da', 'src/third_party/perl': { 'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + 'ac0d98b5cee6c024b0cffeb4f8f45b6fc5ccdb78', @@ -1384,7 +1384,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@98c9c09ca5ff59cdc9120a58e5adae9a201a9c1f', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@cdd88f554acbe96eea5126535fe546c88e5f3ab1', 'condition': 'checkout_src_internal', },
diff --git a/ash/display/display_prefs_unittest.cc b/ash/display/display_prefs_unittest.cc index 523c551..80b2bbf 100644 --- a/ash/display/display_prefs_unittest.cc +++ b/ash/display/display_prefs_unittest.cc
@@ -1402,6 +1402,13 @@ // Load the preferences and simulate a native display reconfiguration. Expect // that we are mirroring now. LoadDisplayPreferences(); + + // Simulate a change in display configuration between loading the prefs, and + // reconfiguring after the prefs have been loaded. Make sure that the external + // display mirror configs are not overwritten, and the loaded prefs will be + // applied. + display_manager()->SetMirrorMode(display::MirrorMode::kOff, base::nullopt); + display_manager()->OnNativeDisplaysChanged(display_info_list); EXPECT_TRUE(display_manager()->IsInMirrorMode()); }
diff --git a/ash/shelf/shelf_tooltip_preview_bubble.cc b/ash/shelf/shelf_tooltip_preview_bubble.cc index 5825b39b2..d8f7c75 100644 --- a/ash/shelf/shelf_tooltip_preview_bubble.cc +++ b/ash/shelf/shelf_tooltip_preview_bubble.cc
@@ -9,11 +9,15 @@ #include "ash/wm/pip/pip_positioner.h" #include "ash/wm/window_preview_view.h" #include "base/strings/utf_string_conversions.h" +#include "ui/display/screen.h" #include "ui/views/bubble/bubble_frame_view.h" #include "ui/views/layout/box_layout.h" namespace ash { +// The delay after which a preview bubble gets dismissed (after the mouse +// has gone away for instance).s +constexpr int kPreviewBubbleDismissDelay = 350; // The padding inside the tooltip. constexpr int kTooltipPaddingTop = 8; @@ -41,6 +45,9 @@ set_border_radius(kPreviewBubbleBorderRadius); // The parent class sets non-zero margins. Reset them to zero. set_margins(gfx::Insets()); + // We hide this tooltip on mouse exit, so we want to get enter/exit events + // at this level, even for subviews. + set_notify_enter_exit_on_child(true); SetLayoutManager(std::make_unique<views::BoxLayout>( views::BoxLayout::kHorizontal, @@ -66,10 +73,11 @@ void ShelfTooltipPreviewBubble::RemovePreview(WindowPreview* to_remove) { base::Erase(previews_, to_remove); RemoveChildView(to_remove); - // If we don't have any previews left, close the tooltip. - if (previews_.empty()) { + // If we don't have any previews left, close the tooltip. Bypass + // considerations of where the mouse pointer is when this happens: we don't + // want to show an empty tooltip even if the mouse is on it. + if (previews_.empty()) manager_->Close(); - } } gfx::Rect ShelfTooltipPreviewBubble::GetBubbleBounds() { @@ -86,6 +94,10 @@ return bounds; } +void ShelfTooltipPreviewBubble::OnMouseExited(const ui::MouseEvent& event) { + DismissAfterDelay(); +} + bool ShelfTooltipPreviewBubble::ShouldCloseOnPressDown() { return false; } @@ -105,12 +117,35 @@ return std::min(max_ratio, kShelfTooltipPreviewMaxRatio); } +void ShelfTooltipPreviewBubble::DismissAfterDelay() { + dismiss_timer_.Start( + FROM_HERE, base::TimeDelta::FromMilliseconds(kPreviewBubbleDismissDelay), + base::BindOnce(&ShelfTooltipPreviewBubble::Dismiss, + base::Unretained(this))); +} + +void ShelfTooltipPreviewBubble::Dismiss() { + dismiss_timer_.Stop(); + + const auto cursor_position = + display::Screen::GetScreen()->GetCursorScreenPoint(); + // Cancel dismissal if the mouse is within our bounds again, or if it's + // within the anchor's bounds. That way the preview tooltip will remain + // shown if the mouse goes between the bubble and its anchor. + if (GetBoundsInScreen().Contains(cursor_position) || + GetAnchorRect().Contains(cursor_position)) { + return; + } + manager_->Close(); +} + void ShelfTooltipPreviewBubble::OnPreviewDismissed(WindowPreview* preview) { RemovePreview(preview); } void ShelfTooltipPreviewBubble::OnPreviewActivated(WindowPreview* preview) { - // Always close the tooltip when a window has been focused. + // Always close the tooltip when a window has been focused. Bypass + // considerations of where the mouse pointer is when this happens. manager_->Close(); }
diff --git a/ash/shelf/shelf_tooltip_preview_bubble.h b/ash/shelf/shelf_tooltip_preview_bubble.h index 354aac7..3df5896 100644 --- a/ash/shelf/shelf_tooltip_preview_bubble.h +++ b/ash/shelf/shelf_tooltip_preview_bubble.h
@@ -13,6 +13,7 @@ #include "ash/shelf/shelf_tooltip_manager.h" #include "ash/shelf/window_preview.h" #include "ash/wm/window_mirror_view.h" +#include "base/timer/timer.h" #include "ui/aura/window.h" #include "ui/views/controls/label.h" @@ -35,6 +36,7 @@ // BubbleDialogDelegateView overrides: gfx::Rect GetBubbleBounds() override; + void OnMouseExited(const ui::MouseEvent& event) override; // ShelfBubble: bool ShouldCloseOnPressDown() override; @@ -45,10 +47,13 @@ void OnPreviewDismissed(WindowPreview* preview) override; void OnPreviewActivated(WindowPreview* preview) override; + void DismissAfterDelay(); + void Dismiss(); + std::vector<WindowPreview*> previews_; - // Preferred size for the tooltip. ShelfTooltipManager* manager_; + base::OneShotTimer dismiss_timer_; const ShelfAlignment shelf_alignment_;
diff --git a/base/allocator/partition_allocator/partition_alloc_perftest.cc b/base/allocator/partition_allocator/partition_alloc_perftest.cc index f143659..85b782a5 100644 --- a/base/allocator/partition_allocator/partition_alloc_perftest.cc +++ b/base/allocator/partition_allocator/partition_alloc_perftest.cc
@@ -7,6 +7,8 @@ #include "base/time/time.h" #include "base/timer/lap_timer.h" +#include "build/build_config.h" + #include "testing/gtest/include/gtest/gtest.h" #include "testing/perf/perf_test.h" @@ -100,7 +102,13 @@ timer_.LapsPerSecond(), "runs/s", true); } -TEST_F(MemoryAllocationPerfTest, MultiBucket) { +// Failing on Nexus5x: crbug.com/949838 +#if defined(OS_ANDROID) +#define MAYBE_MultiBucket DISABLED_MultiBucket +#else +#define MAYBE_MultiBucket MultiBucket +#endif +TEST_F(MemoryAllocationPerfTest, MAYBE_MultiBucket) { timer_.Reset(); MemoryAllocationPerfNode* first = reinterpret_cast<MemoryAllocationPerfNode*>( alloc_.root()->Alloc(40, "<testing>"));
diff --git a/base/android/android_image_reader_compat.cc b/base/android/android_image_reader_compat.cc index 0101516..62c153ba 100644 --- a/base/android/android_image_reader_compat.cc +++ b/base/android/android_image_reader_compat.cc
@@ -56,9 +56,10 @@ // devices, this is unlikely to happen in the foreseeable future, so we use // dynamic loading. - // Functions are not present for android version older than OREO + // Functions are not present for android version older than OREO. + // Currently we want to enable AImageReader only for android P+ devices. if (base::android::BuildInfo::GetInstance()->sdk_int() < - base::android::SDK_VERSION_OREO) { + base::android::SDK_VERSION_P) { return false; }
diff --git a/base/containers/span.h b/base/containers/span.h index c22d51f..f56172d1a065 100644 --- a/base/containers/span.h +++ b/base/containers/span.h
@@ -492,7 +492,8 @@ } template <typename Container, - typename T = typename Container::value_type, + typename T = std::remove_pointer_t< + decltype(base::data(std::declval<Container&>()))>, typename = internal::EnableIfSpanCompatibleContainer<Container&, T>> constexpr span<T> make_span(Container& container) noexcept { return container; @@ -500,7 +501,8 @@ template < typename Container, - typename T = const typename Container::value_type, + typename T = std::remove_pointer_t< + decltype(base::data(std::declval<const Container&>()))>, typename = internal::EnableIfSpanCompatibleContainer<const Container&, T>> constexpr span<T> make_span(const Container& container) noexcept { return container; @@ -508,7 +510,8 @@ template <size_t N, typename Container, - typename T = typename Container::value_type, + typename T = std::remove_pointer_t< + decltype(base::data(std::declval<Container&>()))>, typename = internal::EnableIfSpanCompatibleContainer<Container&, T>> constexpr span<T, N> make_span(Container& container) noexcept { return span<T, N>(container); @@ -517,7 +520,8 @@ template < size_t N, typename Container, - typename T = const typename Container::value_type, + typename T = std::remove_pointer_t< + decltype(base::data(std::declval<const Container&>()))>, typename = internal::EnableIfSpanCompatibleContainer<const Container&, T>> constexpr span<T, N> make_span(const Container& container) noexcept { return span<T, N>(container);
diff --git a/base/containers/span_unittest.cc b/base/containers/span_unittest.cc index 0705a97..7f8f8df 100644 --- a/base/containers/span_unittest.cc +++ b/base/containers/span_unittest.cc
@@ -1001,11 +1001,14 @@ EXPECT_EQ(nullptr, empty_span.data()); std::vector<int> vector = {1, 1, 2, 3, 5, 8}; - span<int> span(vector.data(), vector.size()); + span<int> expected_span(vector.data(), vector.size()); auto made_span = make_span(vector.data(), vector.size()); - EXPECT_EQ(span.data(), made_span.data()); - EXPECT_EQ(span.size(), made_span.size()); + EXPECT_EQ(expected_span.data(), made_span.data()); + EXPECT_EQ(expected_span.size(), made_span.size()); static_assert(decltype(made_span)::extent == dynamic_extent, ""); + static_assert( + std::is_same<decltype(expected_span), decltype(made_span)>::value, + "the type of made_span differs from expected_span!"); } TEST(SpanTest, MakeSpanFromPointerPair) { @@ -1015,93 +1018,130 @@ EXPECT_EQ(nullptr, empty_span.data()); std::vector<int> vector = {1, 1, 2, 3, 5, 8}; - span<int> span(vector.data(), vector.size()); + span<int> expected_span(vector.data(), vector.size()); auto made_span = make_span(vector.data(), vector.data() + vector.size()); - EXPECT_EQ(span.data(), made_span.data()); - EXPECT_EQ(span.size(), made_span.size()); + EXPECT_EQ(expected_span.data(), made_span.data()); + EXPECT_EQ(expected_span.size(), made_span.size()); static_assert(decltype(made_span)::extent == dynamic_extent, ""); + static_assert( + std::is_same<decltype(expected_span), decltype(made_span)>::value, + "the type of made_span differs from expected_span!"); } TEST(SpanTest, MakeSpanFromConstexprArray) { static constexpr int kArray[] = {1, 2, 3, 4, 5}; - constexpr span<const int> span(kArray); - EXPECT_EQ(span.data(), make_span(kArray).data()); - EXPECT_EQ(span.size(), make_span(kArray).size()); - static_assert(decltype(make_span(kArray))::extent == 5, ""); + constexpr span<const int, 5> expected_span(kArray); + constexpr auto made_span = make_span(kArray); + EXPECT_EQ(expected_span.data(), made_span.data()); + EXPECT_EQ(expected_span.size(), made_span.size()); + static_assert(decltype(made_span)::extent == 5, ""); + static_assert( + std::is_same<decltype(expected_span), decltype(made_span)>::value, + "the type of made_span differs from expected_span!"); } TEST(SpanTest, MakeSpanFromStdArray) { const std::array<int, 5> kArray = {{1, 2, 3, 4, 5}}; - span<const int> span(kArray); - EXPECT_EQ(span.data(), make_span(kArray).data()); - EXPECT_EQ(span.size(), make_span(kArray).size()); - static_assert(decltype(make_span(kArray))::extent == 5, ""); + span<const int, 5> expected_span(kArray); + auto made_span = make_span(kArray); + EXPECT_EQ(expected_span.data(), made_span.data()); + EXPECT_EQ(expected_span.size(), made_span.size()); + static_assert(decltype(made_span)::extent == 5, ""); + static_assert( + std::is_same<decltype(expected_span), decltype(made_span)>::value, + "the type of made_span differs from expected_span!"); } TEST(SpanTest, MakeSpanFromConstContainer) { const std::vector<int> vector = {-1, -2, -3, -4, -5}; - span<const int> span(vector); - EXPECT_EQ(span.data(), make_span(vector).data()); - EXPECT_EQ(span.size(), make_span(vector).size()); - static_assert(decltype(make_span(vector))::extent == dynamic_extent, ""); + span<const int> expected_span(vector); + auto made_span = make_span(vector); + EXPECT_EQ(expected_span.data(), made_span.data()); + EXPECT_EQ(expected_span.size(), made_span.size()); + static_assert(decltype(made_span)::extent == dynamic_extent, ""); + static_assert( + std::is_same<decltype(expected_span), decltype(made_span)>::value, + "the type of made_span differs from expected_span!"); } TEST(SpanTest, MakeStaticSpanFromConstContainer) { const std::vector<int> vector = {-1, -2, -3, -4, -5}; - span<const int, 5> span(vector); - EXPECT_EQ(span.data(), make_span<5>(vector).data()); - EXPECT_EQ(span.size(), make_span<5>(vector).size()); - static_assert(decltype(make_span<5>(vector))::extent == 5, ""); + span<const int, 5> expected_span(vector); + auto made_span = make_span<5>(vector); + EXPECT_EQ(expected_span.data(), made_span.data()); + EXPECT_EQ(expected_span.size(), made_span.size()); + static_assert(decltype(made_span)::extent == 5, ""); + static_assert( + std::is_same<decltype(expected_span), decltype(made_span)>::value, + "the type of made_span differs from expected_span!"); } TEST(SpanTest, MakeSpanFromContainer) { std::vector<int> vector = {-1, -2, -3, -4, -5}; - span<int> span(vector); - EXPECT_EQ(span.data(), make_span(vector).data()); - EXPECT_EQ(span.size(), make_span(vector).size()); - static_assert(decltype(make_span(vector))::extent == dynamic_extent, ""); + span<int> expected_span(vector); + auto made_span = make_span(vector); + EXPECT_EQ(expected_span.data(), made_span.data()); + EXPECT_EQ(expected_span.size(), made_span.size()); + static_assert(decltype(made_span)::extent == dynamic_extent, ""); + static_assert( + std::is_same<decltype(expected_span), decltype(made_span)>::value, + "the type of made_span differs from expected_span!"); } TEST(SpanTest, MakeStaticSpanFromContainer) { std::vector<int> vector = {-1, -2, -3, -4, -5}; - span<int, 5> span(vector); - EXPECT_EQ(span.data(), make_span<5>(vector).data()); - EXPECT_EQ(span.size(), make_span<5>(vector).size()); + span<int, 5> expected_span(vector); + auto made_span = make_span<5>(vector); + EXPECT_EQ(expected_span.data(), make_span<5>(vector).data()); + EXPECT_EQ(expected_span.size(), make_span<5>(vector).size()); static_assert(decltype(make_span<5>(vector))::extent == 5, ""); + static_assert( + std::is_same<decltype(expected_span), decltype(made_span)>::value, + "the type of made_span differs from expected_span!"); } TEST(SpanTest, MakeSpanFromDynamicSpan) { static constexpr int kArray[] = {1, 2, 3, 4, 5}; - constexpr span<const int> span(kArray); - static_assert(std::is_same<decltype(span)::element_type, - decltype(make_span(span))::element_type>::value, + constexpr span<const int> expected_span(kArray); + constexpr auto made_span = make_span(expected_span); + static_assert(std::is_same<decltype(expected_span)::element_type, + decltype(made_span)::element_type>::value, "make_span(span) should have the same element_type as span"); - static_assert(span.data() == make_span(span).data(), + static_assert(expected_span.data() == made_span.data(), "make_span(span) should have the same data() as span"); - static_assert(span.size() == make_span(span).size(), + static_assert(expected_span.size() == made_span.size(), "make_span(span) should have the same size() as span"); - static_assert(decltype(make_span(span))::extent == decltype(span)::extent, + static_assert(decltype(made_span)::extent == decltype(expected_span)::extent, "make_span(span) should have the same extent as span"); + + static_assert( + std::is_same<decltype(expected_span), decltype(made_span)>::value, + "the type of made_span differs from expected_span!"); } TEST(SpanTest, MakeSpanFromStaticSpan) { static constexpr int kArray[] = {1, 2, 3, 4, 5}; - constexpr span<const int, 5> span(kArray); - static_assert(std::is_same<decltype(span)::element_type, - decltype(make_span(span))::element_type>::value, + constexpr span<const int, 5> expected_span(kArray); + constexpr auto made_span = make_span(expected_span); + static_assert(std::is_same<decltype(expected_span)::element_type, + decltype(made_span)::element_type>::value, "make_span(span) should have the same element_type as span"); - static_assert(span.data() == make_span(span).data(), + static_assert(expected_span.data() == made_span.data(), "make_span(span) should have the same data() as span"); - static_assert(span.size() == make_span(span).size(), + static_assert(expected_span.size() == made_span.size(), "make_span(span) should have the same size() as span"); - static_assert(decltype(make_span(span))::extent == decltype(span)::extent, + static_assert(decltype(made_span)::extent == decltype(expected_span)::extent, "make_span(span) should have the same extent as span"); + + static_assert( + std::is_same<decltype(expected_span), decltype(made_span)>::value, + "the type of made_span differs from expected_span!"); } TEST(SpanTest, StdTupleSize) {
diff --git a/base/containers/span_unittest.nc b/base/containers/span_unittest.nc index 9859495..5ef2ec999 100644 --- a/base/containers/span_unittest.nc +++ b/base/containers/span_unittest.nc
@@ -249,6 +249,13 @@ return std::get<0>(s); } +#elif defined(NCTEST_CONST_VECTOR_DEDUCES_AS_CONST_SPAN) // [r"fatal error: no viable conversion from 'span<const int>' to 'span<int>'"] + +int WontCompile() { + const std::vector<int> v; + span<int> s = make_span(v); +} + #endif } // namespace base
diff --git a/base/sampling_heap_profiler/sampling_heap_profiler.cc b/base/sampling_heap_profiler/sampling_heap_profiler.cc index e7183b29..f8736ef 100644 --- a/base/sampling_heap_profiler/sampling_heap_profiler.cc +++ b/base/sampling_heap_profiler/sampling_heap_profiler.cc
@@ -105,12 +105,18 @@ return 0; } #endif - PoissonAllocationSampler::Get()->AddSamplesObserver(this); + + AutoLock lock(start_stop_mutex_); + if (!running_sessions_++) + PoissonAllocationSampler::Get()->AddSamplesObserver(this); return last_sample_ordinal_; } void SamplingHeapProfiler::Stop() { - PoissonAllocationSampler::Get()->RemoveSamplesObserver(this); + AutoLock lock(start_stop_mutex_); + DCHECK_GT(running_sessions_, 0); + if (!--running_sessions_) + PoissonAllocationSampler::Get()->RemoveSamplesObserver(this); } void SamplingHeapProfiler::SetSamplingInterval(size_t sampling_interval) {
diff --git a/base/sampling_heap_profiler/sampling_heap_profiler.h b/base/sampling_heap_profiler/sampling_heap_profiler.h index e12898b..398bf0e9 100644 --- a/base/sampling_heap_profiler/sampling_heap_profiler.h +++ b/base/sampling_heap_profiler/sampling_heap_profiler.h
@@ -5,6 +5,7 @@ #ifndef BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_ #define BASE_SAMPLING_HEAP_PROFILER_SAMPLING_HEAP_PROFILER_H_ +#include <atomic> #include <unordered_map> #include <unordered_set> #include <vector> @@ -124,13 +125,21 @@ // deleted. std::unordered_set<const char*> strings_; + // Mutex to make |running_sessions_| and Add/Remove samples observer access + // atomic. + Lock start_stop_mutex_; + + // Number of the running sessions. + int running_sessions_ = 0; + // Last sample ordinal used to mark samples recorded during single session. - uint32_t last_sample_ordinal_ = 1; + std::atomic<uint32_t> last_sample_ordinal_{1}; // Whether it should record thread names. - bool record_thread_names_ = false; + std::atomic<bool> record_thread_names_{false}; friend class NoDestructor<SamplingHeapProfiler>; + friend class SamplingHeapProfilerTest; DISALLOW_COPY_AND_ASSIGN(SamplingHeapProfiler); };
diff --git a/base/sampling_heap_profiler/sampling_heap_profiler_unittest.cc b/base/sampling_heap_profiler/sampling_heap_profiler_unittest.cc index 8e08e01..d1623e71 100644 --- a/base/sampling_heap_profiler/sampling_heap_profiler_unittest.cc +++ b/base/sampling_heap_profiler/sampling_heap_profiler_unittest.cc
@@ -10,6 +10,7 @@ #include "base/allocator/allocator_shim.h" #include "base/debug/alias.h" #include "base/rand_util.h" +#include "base/synchronization/waitable_event.h" #include "base/threading/simple_thread.h" #include "build/build_config.h" #include "testing/gtest/include/gtest/gtest.h" @@ -28,6 +29,18 @@ size_t GetNextSample(size_t mean_interval) { return PoissonAllocationSampler::GetNextSampleInterval(mean_interval); } + + static int GetRunningSessionsCount() { + return SamplingHeapProfiler::Get()->running_sessions_; + } + + static void RunStartStopLoop(SamplingHeapProfiler* profiler) { + for (int i = 0; i < 100000; ++i) { + profiler->Start(); + EXPECT_LE(1, GetRunningSessionsCount()); + profiler->Stop(); + } + } }; class SamplesCollector : public PoissonAllocationSampler::SamplesObserver { @@ -180,14 +193,14 @@ TEST_F(SamplingHeapProfilerTest, DISABLED_ParallelLargeSmallStats) { CheckAllocationPattern([]() { - SimpleThread* t1 = new MyThread1(); - SimpleThread* t2 = new MyThread2(); - t1->Start(); - t2->Start(); + MyThread1 t1; + MyThread1 t2; + t1.Start(); + t2.Start(); for (int i = 0; i < kNumberOfAllocations; ++i) Allocate3(); - t1->Join(); - t2->Join(); + t1.Join(); + t2.Join(); }); } @@ -237,4 +250,39 @@ sampler->RemoveSamplesObserver(&collector); } +class StartStopThread : public SimpleThread { + public: + StartStopThread(WaitableEvent* event) + : SimpleThread("MyThread2"), event_(event) {} + void Run() override { + auto* profiler = SamplingHeapProfiler::Get(); + event_->Signal(); + SamplingHeapProfilerTest::RunStartStopLoop(profiler); + } + + private: + WaitableEvent* event_; +}; + +TEST_F(SamplingHeapProfilerTest, StartStop) { + auto* profiler = SamplingHeapProfiler::Get(); + EXPECT_EQ(0, GetRunningSessionsCount()); + profiler->Start(); + EXPECT_EQ(1, GetRunningSessionsCount()); + profiler->Start(); + EXPECT_EQ(2, GetRunningSessionsCount()); + profiler->Stop(); + EXPECT_EQ(1, GetRunningSessionsCount()); + profiler->Stop(); + EXPECT_EQ(0, GetRunningSessionsCount()); + + WaitableEvent event; + StartStopThread thread(&event); + thread.Start(); + event.Wait(); + RunStartStopLoop(profiler); + thread.Join(); + EXPECT_EQ(0, GetRunningSessionsCount()); +} + } // namespace base
diff --git a/base/type_id.h b/base/type_id.h index ac44ee1..0c284bf 100644 --- a/base/type_id.h +++ b/base/type_id.h
@@ -80,7 +80,7 @@ #if defined(__clang__) "base::internal::UniqueIdFromType() [Type = (anonymous namespace)::"; #elif defined(COMPILER_GCC) - "base::internal::UniqueIdFromType() [with T = {anonymous}::"; + "base::internal::UniqueIdFromType() [with Type = {anonymous}::"; #elif defined(COMPILER_MSVC) "base::internal::UniqueIdFromType<`anonymous namespace'::"; #else
diff --git a/base/type_id_unittest.cc b/base/type_id_unittest.cc index 8c32334..2bf28ae 100644 --- a/base/type_id_unittest.cc +++ b/base/type_id_unittest.cc
@@ -76,8 +76,8 @@ TypeIdTestSupportB::GetTypeIdForUniquePtrInt()); } -// TODO(crbug.com/928806): Failing consistently on Android. -#if defined(OS_ANDROID) +// TODO(crbug.com/928806): Failing consistently on Android and GCC +#if defined(OS_ANDROID) || (defined(COMPILER_GCC) && !defined(__clang__)) TEST(TypeId, DISABLED_IdenticalTypesFromComponentAndStaticLibrary) { #else TEST(TypeId, IdenticalTypesFromComponentAndStaticLibrary) {
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index dfac1051..aaa72eb 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8916983715801543744 \ No newline at end of file +8916875429194723312 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 8fa3ec7..5baed26 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8916982364174025824 \ No newline at end of file +8916873457256596624 \ No newline at end of file
diff --git a/cc/trees/layer_tree_host.cc b/cc/trees/layer_tree_host.cc index 687ab1b..59c4845 100644 --- a/cc/trees/layer_tree_host.cc +++ b/cc/trees/layer_tree_host.cc
@@ -883,9 +883,11 @@ if (inner_viewport_scroll_delta.IsZero() && info.page_scale_delta == 1.f && info.elastic_overscroll_delta.IsZero() && !info.top_controls_delta && !info.browser_controls_constraint_changed && - !info.scroll_gesture_did_end) { + !info.scroll_gesture_did_end && + info.is_pinch_gesture_active == is_pinch_gesture_active_from_impl_) { return; } + is_pinch_gesture_active_from_impl_ = info.is_pinch_gesture_active; // Preemptively apply the scroll offset and scale delta here before sending // it to the client. If the client comes back and sets it to the same @@ -1326,11 +1328,16 @@ this, [](Layer* layer) { layer->SetNeedsDisplay(); }); } -void LayerTreeHost::SetExternalPageScaleFactor(float page_scale_factor) { - if (external_page_scale_factor_ == page_scale_factor) +void LayerTreeHost::SetExternalPageScaleFactor( + float page_scale_factor, + bool is_external_pinch_gesture_active) { + if (external_page_scale_factor_ == page_scale_factor && + is_external_pinch_gesture_active_ == is_external_pinch_gesture_active) { return; + } external_page_scale_factor_ = page_scale_factor; + is_external_pinch_gesture_active_ = is_external_pinch_gesture_active; SetNeedsCommit(); } @@ -1651,6 +1658,7 @@ host_impl->SetHasGpuRasterizationTrigger(has_gpu_rasterization_trigger_); host_impl->SetContentHasSlowPaths(content_has_slow_paths_); host_impl->SetContentHasNonAAPaint(content_has_non_aa_paint_); + host_impl->set_pinch_gesture_active(is_external_pinch_gesture_active_); RecordGpuRasterizationHistogram(host_impl); host_impl->SetDebugState(debug_state_);
diff --git a/cc/trees/layer_tree_host.h b/cc/trees/layer_tree_host.h index 85c520d..cd2c6e69 100644 --- a/cc/trees/layer_tree_host.h +++ b/cc/trees/layer_tree_host.h
@@ -471,7 +471,11 @@ // 'external_page_scale_factor', a value that affects raster scale in the // same way that page_scale_factor does, but doesn't affect any geometry // calculations. - void SetExternalPageScaleFactor(float page_scale_factor); + void SetExternalPageScaleFactor(float page_scale_factor, + bool is_external_pinch_gesture_active); + bool is_external_pinch_gesture_active_for_testing() { + return is_external_pinch_gesture_active_; + } // Requests that we force send RenderFrameMetadata with the next frame. void RequestForceSendMetadata() { force_send_metadata_request_ = true; } @@ -805,6 +809,9 @@ float min_page_scale_factor_ = 1.f; float max_page_scale_factor_ = 1.f; float external_page_scale_factor_ = 1.f; + bool is_external_pinch_gesture_active_ = false; + // Used to track the out-bound state for ApplyViewportChanges. + bool is_pinch_gesture_active_from_impl_ = false; int raster_color_space_id_ = -1; gfx::ColorSpace raster_color_space_;
diff --git a/cc/trees/layer_tree_host_impl.h b/cc/trees/layer_tree_host_impl.h index 8e76053..c2d3791e 100644 --- a/cc/trees/layer_tree_host_impl.h +++ b/cc/trees/layer_tree_host_impl.h
@@ -591,6 +591,15 @@ } bool pinch_gesture_active() const { return pinch_gesture_active_; } + // Used to set the pinch gesture active state when the pinch gesture is + // handled on another layer tree. In a page with OOPIFs, only the main + // frame's layer tree directly handles pinch events. But layer trees for + // sub-frames need to know when pinch gestures are active so they can + // throttle the re-rastering. This function allows setting this flag on + // OOPIF layer trees using information sent (initially) from the main-frame. + void set_pinch_gesture_active(bool external_pinch_gesture_active) { + pinch_gesture_active_ = external_pinch_gesture_active; + } void SetTreePriority(TreePriority priority); TreePriority GetTreePriority() const; @@ -1006,6 +1015,15 @@ bool did_scroll_x_for_scroll_gesture_; bool did_scroll_y_for_scroll_gesture_; + // This value is used to allow the compositor to throttle re-rastering during + // pinch gestures, when the page scale factor may be changing frequently. It + // is set in one of two ways: + // i) In a layer tree serving the root of the frame/compositor tree, it is + // directly set during processing of GesturePinch events on the impl thread + // (only the root layer tree has access to these). + // ii) In a layer tree serving a sub-frame in the frame/compositor tree, it + // is set from the main thread during the commit process, using information + // sent from the root layer tree via IPC messaging. bool pinch_gesture_active_ = false; bool pinch_gesture_end_should_clear_scrolling_node_ = false;
diff --git a/chrome/VERSION b/chrome/VERSION index c092988..593c8a2 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=75 MINOR=0 -BUILD=3758 +BUILD=3760 PATCH=0
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni index a71fdbb..b005fbe 100644 --- a/chrome/android/chrome_test_java_sources.gni +++ b/chrome/android/chrome_test_java_sources.gni
@@ -356,6 +356,13 @@ "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestServiceWorkerPaymentAppTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressAndOptionTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShippingAddressChangeTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseDigitalGoodsTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseInvalidDetailsTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseRejectTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseSingleOptionShippingTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseSingleOptionShippingWithUpdateTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseUnsupportedTest.java", + "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseUSOnlyShippingTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowTwiceTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTabTest.java", "javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java",
diff --git a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java index 5112350b..63ce54f 100644 --- a/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java +++ b/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/MultiThumbnailCardProvider.java
@@ -16,9 +16,6 @@ import org.chromium.base.ApiCompatibilityUtils; import org.chromium.base.Callback; -import org.chromium.base.PathUtils; -import org.chromium.base.ThreadUtils; -import org.chromium.base.task.AsyncTask; import org.chromium.base.task.PostTask; import org.chromium.chrome.R; import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; @@ -26,7 +23,6 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector; import org.chromium.content_public.browser.UiThreadTaskTraits; -import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -47,9 +43,10 @@ private final int mSize; private final List<RectF> mRects = new ArrayList<>(4); - private class MultiThumbnailFetchingTask extends AsyncTask<Void> { + private class MultiThumbnailFetcher { private final Tab mInitialTab; private final Callback<Bitmap> mFinalCallback; + private final boolean mForceUpdate; private final List<Tab> mTabs = new ArrayList<>(4); private final AtomicInteger mThumbnailsToFetch = new AtomicInteger(); @@ -57,9 +54,10 @@ private Bitmap mMultiThumbnailBitmap; private String mText; - MultiThumbnailFetchingTask(Tab initialTab, Callback<Bitmap> finalCallback) { + MultiThumbnailFetcher(Tab initialTab, Callback<Bitmap> finalCallback, boolean forceUpdate) { mFinalCallback = finalCallback; mInitialTab = initialTab; + mForceUpdate = forceUpdate; } private void initializeAndStartFetching(Tab tab) { @@ -99,22 +97,14 @@ // Fetch and draw all. for (int i = 0; i < 4; i++) { if (mTabs.get(i) != null) { - if (hasThumbnailFileForTab(mTabs.get(i).getId())) { - final int index = i; - mTabContentManager.getTabThumbnailWithCallback(mTabs.get(i), result -> { - drawBitmapOnCanvasWithFrame(result, index, mEmptyThumbnailPaint); - if (mThumbnailsToFetch.decrementAndGet() == 0) { - PostTask.postTask(UiThreadTaskTraits.USER_VISIBLE, - () -> mFinalCallback.onResult(mMultiThumbnailBitmap)); - } - }, false); - } else { - drawBitmapOnCanvasWithFrame(null, i, mEmptyThumbnailPaint); + final int index = i; + mTabContentManager.getTabThumbnailWithCallback(mTabs.get(i), result -> { + drawBitmapOnCanvasWithFrame(result, index, mEmptyThumbnailPaint); if (mThumbnailsToFetch.decrementAndGet() == 0) { PostTask.postTask(UiThreadTaskTraits.USER_VISIBLE, () -> mFinalCallback.onResult(mMultiThumbnailBitmap)); } - } + }, mForceUpdate && i == 0); } else { drawBitmapOnCanvasWithFrame(null, i, mEmptyThumbnailPaint); if (mText != null && i == 3) { @@ -148,14 +138,9 @@ mCanvas.drawRoundRect(mRects.get(index), mRadius, mRadius, mThumbnailFramePaint); } - @Override - protected Void doInBackground() { + private void fetch() { initializeAndStartFetching(mInitialTab); - return null; } - - @Override - protected void onPostExecute(Void aVoid) {} } MultiThumbnailCardProvider(Context context, TabContentManager tabContentManager, @@ -212,15 +197,6 @@ return; } - new MultiThumbnailFetchingTask(tab, finalCallback) - .executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); - } - - private static boolean hasThumbnailFileForTab(int tabId) { - ThreadUtils.assertOnBackgroundThread(); - - // The thumbnail file path for a tab with id, ID is "cache_directory_path/ID". - File file = new File(PathUtils.getThumbnailCacheDirectory() + "/" + tabId); - return file.exists(); + new MultiThumbnailFetcher(tab, finalCallback, forceUpdate).fetch(); } }
diff --git a/chrome/android/java/res/values/ids.xml b/chrome/android/java/res/values/ids.xml index e7ee576..b658a52 100644 --- a/chrome/android/java/res/values/ids.xml +++ b/chrome/android/java/res/values/ids.xml
@@ -67,6 +67,8 @@ <item type="id" name="payments_add_option_button" /> <item type="id" name="payments_edit_cancel_button" /> <item type="id" name="payments_edit_checkbox" /> + <item type="id" name="payments_description_label" /> + <item type="id" name="payments_warning_label" /> <!-- Password update prompt --> <item type="id" name="password_infobar_accounts_spinner" />
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java index a9e64c68..40f7c76 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestFactory.java
@@ -38,7 +38,7 @@ } @Override - public void show(boolean isUserGesture) { + public void show(boolean isUserGesture, boolean waitForUpdatedDetails) { if (mClient != null) { mClient.onError(PaymentErrorReason.USER_CANCEL); mClient.close();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java index d4b6a4b..5547717 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/PaymentRequestImpl.java
@@ -109,6 +109,13 @@ */ public interface PaymentRequestServiceObserverForTest { /** + * Called after an instance of PaymentRequestImpl has been created. + * + * @param paymentRequest The newly created instance of PaymentRequestImpl. + */ + void onPaymentRequestCreated(PaymentRequestImpl paymentRequest); + + /** * Called when an abort request was denied. */ void onPaymentRequestServiceUnableToAbort(); @@ -302,6 +309,7 @@ private boolean mHideServerAutofillInstruments; private ContactEditor mContactEditor; private boolean mHasRecordedAbortReason; + private boolean mWaitForUpdatedDetails; private Map<String, CurrencyFormatter> mCurrencyFormatterMap; private TabModelSelector mObservedTabModelSelector; private TabModel mObservedTabModel; @@ -375,6 +383,8 @@ mJourneyLogger = new JourneyLogger(mIsIncognito, mWebContents); mCurrencyFormatterMap = new HashMap<>(); + + if (sObserverForTest != null) sObserverForTest.onPaymentRequestCreated(this); } /** @@ -472,7 +482,19 @@ } mJourneyLogger.setRequestedPaymentMethodTypes(mMerchantSupportsAutofillPaymentInstruments, requestedMethodGoogle, requestedMethodOther); + calculateWhetherShouldSkipShowingPaymentRequestUi( + false /* skipUiForNonUrlPaymentMethodIdentifiersForTest */); + } + /** + * Calculate whether the browser payment sheet should be skipped directly into the payment app. + * + * @param skipUiForNonUrlPaymentMethodIdentifiersForTest Whether non-URL payment method + * identifiers should skip UI. Used only + * in tests. + */ + private void calculateWhetherShouldSkipShowingPaymentRequestUi( + boolean skipUiForNonUrlPaymentMethodIdentifiersForTest) { // If there is a single payment method and the merchant has not requested any other // information, we can safely go directly to the payment app instead of showing // Payment Request UI. @@ -485,7 +507,8 @@ // This excludes AutofillPaymentApp as its UI is rendered inline in // the payment request UI, thus can't be skipped. && mMethodData.keySet().iterator().next() != null - && mMethodData.keySet().iterator().next().startsWith(UrlConstants.HTTPS_URL_PREFIX); + && (mMethodData.keySet().iterator().next().startsWith(UrlConstants.HTTPS_URL_PREFIX) + || skipUiForNonUrlPaymentMethodIdentifiersForTest); } /** @return Whether the UI was built. */ @@ -526,7 +549,7 @@ false /* includeNameInLabel */); } - if (mRequestShipping) { + if (mRequestShipping && !mWaitForUpdatedDetails) { createShippingSection(activity, Collections.unmodifiableList(profiles)); } @@ -622,7 +645,7 @@ * Called by the merchant website to show the payment request to the user. */ @Override - public void show(boolean isUserGesture) { + public void show(boolean isUserGesture, boolean waitForUpdatedDetails) { if (mClient == null) return; if (mUI != null) { @@ -657,6 +680,8 @@ } mIsUserGestureShow = isUserGesture; + mWaitForUpdatedDetails = waitForUpdatedDetails; + if (!mShouldSkipShowingPaymentRequestUi) { if (!buildUI(chromeActivity)) return; mUI.show(); @@ -669,7 +694,7 @@ // If we are skipping showing the Payment Request UI, we should call into the // PaymentApp immediately after we determine the instruments are ready and UI is shown. if (mShouldSkipShowingPaymentRequestUi && isFinishedQueryingPaymentApps() - && mIsCurrentPaymentRequestShowing) { + && mIsCurrentPaymentRequestShowing && !mWaitForUpdatedDetails) { assert !mPaymentMethodsSection.isEmpty(); PaymentInstrument selectedInstrument = @@ -838,6 +863,11 @@ public void updateWith(PaymentDetails details) { if (mClient == null) return; + if (mWaitForUpdatedDetails) { + initializeWithUpdatedDetails(details); + return; + } + if (mUI == null) { mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER); disconnectFromClientWithDebugMessage( @@ -845,6 +875,14 @@ return; } + if (!mRequestShipping) { + mJourneyLogger.setAborted(AbortReason.INVALID_DATA_FROM_RENDERER); + disconnectFromClientWithDebugMessage( + "PaymentRequestUpdateEvent.updateWith() called without passing a promise into " + + "PaymentRequest.show() and without requestShipping:true"); + return; + } + if (!parseAndValidateDetailsOrDisconnectFromClient(details)) return; if (mInvokedPaymentInstrument != null) { @@ -872,6 +910,49 @@ enableUserInterfaceAfterPaymentRequestUpdateEvent(); } + private void initializeWithUpdatedDetails(PaymentDetails details) { + assert mWaitForUpdatedDetails; + + ChromeActivity chromeActivity = ChromeActivity.fromWebContents(mWebContents); + if (chromeActivity == null) { + mJourneyLogger.setNotShown(NotShownReason.OTHER); + disconnectFromClientWithDebugMessage("Unable to find Chrome activity"); + return; + } + + if (!parseAndValidateDetailsOrDisconnectFromClient(details)) return; + + if (details.total == null) { + mJourneyLogger.setNotShown(NotShownReason.OTHER); + disconnectFromClientWithDebugMessage( + "PaymentRequestUpdateEvent.updateWith() called without a total amount when " + + "resolving the promise passed into PaymentRequest.show()"); + return; + } + + if (!TextUtils.isEmpty(details.error)) { + mJourneyLogger.setNotShown(NotShownReason.OTHER); + disconnectFromClientWithDebugMessage( + "PaymentRequestUpdateEvent.updateWith() called with an error when resolving " + + "the promise passed into PaymentRequest.show()"); + return; + } + + if (mRequestShipping) { + createShippingSection(chromeActivity, + Collections.unmodifiableList( + PersonalDataManager.getInstance().getProfilesToSuggest( + false /* includeNameInLabel */))); + } + + if (!mShouldSkipShowingPaymentRequestUi) { + enableUserInterfaceAfterPaymentRequestUpdateEvent(); + } + + mWaitForUpdatedDetails = false; + triggerPaymentAppUiSkipIfApplicable(chromeActivity); + } + /** * Called when the merchant received a new shipping address, shipping option, or payment method * info, but did not update the payment details in response. @@ -896,11 +977,13 @@ } private void enableUserInterfaceAfterPaymentRequestUpdateEvent() { - if (mPaymentInformationCallback != null) { + if (mPaymentInformationCallback != null && mPaymentMethodsSection != null) { providePaymentInformation(); } else { mUI.updateOrderSummarySection(mUiShoppingCart); - mUI.updateSection(PaymentRequestUI.DataType.SHIPPING_OPTIONS, mUiShippingOptions); + if (mRequestShipping) { + mUI.updateSection(PaymentRequestUI.DataType.SHIPPING_OPTIONS, mUiShippingOptions); + } } } @@ -1124,7 +1207,7 @@ public void getDefaultPaymentInformation(Callback<PaymentInformation> callback) { mPaymentInformationCallback = callback; - if (mPaymentMethodsSection == null) return; + if (mPaymentMethodsSection == null || mWaitForUpdatedDetails) return; mHandler.post(() -> { if (mUI != null) providePaymentInformation(); @@ -1884,7 +1967,9 @@ updateInstrumentModifiedTotals(); // UI has requested the full list of payment instruments. Provide it now. - if (mPaymentInformationCallback != null) providePaymentInformation(); + if (mPaymentInformationCallback != null && !mWaitForUpdatedDetails) { + providePaymentInformation(); + } SettingsAutofillAndPaymentsObserver.getInstance().registerObserver(this); @@ -2123,6 +2208,12 @@ sIsLocalCanMakePaymentQueryQuotaEnforcedForTest = true; } + @VisibleForTesting + /* package */ void setSkipUIForNonURLPaymentMethodIdentifiersForTest() { + calculateWhetherShouldSkipShowingPaymentRequestUi( + true /* skipUiForNonUrlPaymentMethodIdentifiersForTest */); + } + /** * Compares two payment instruments by frecency. * Return negative value if a has strictly lower frecency score than b.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java index 2a39ce30..77b0ab18 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/payments/ui/PaymentRequestSection.java
@@ -991,11 +991,13 @@ ApiCompatibilityUtils.setTextAppearance( labelView, R.style.TextAppearance_BlackBody); + labelView.setId(R.id.payments_description_label); } else if (mRowType == OPTION_ROW_TYPE_WARNING) { // Warnings use three columns. columnSpan = 3; ApiCompatibilityUtils.setTextAppearance( labelView, R.style.TextAppearance_PaymentsUiSectionWarningText); + labelView.setId(R.id.payments_warning_label); } // The label spans two columns if no option or edit icon, or spans three columns if
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseDigitalGoodsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseDigitalGoodsTest.java new file mode 100644 index 0000000..7029a80 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseDigitalGoodsTest.java
@@ -0,0 +1,111 @@ +// Copyright 2019 The Chromium 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.payments; + +import android.support.test.filters.MediumTest; + +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ui.DisableAnimationsTestRule; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * A payment integration test for the show promise with digital goods. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +public class PaymentRequestShowPromiseDigitalGoodsTest implements MainActivityStartCallback { + // Disable animations to reduce flakiness. + @ClassRule + public static DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule(); + + @Rule + public PaymentRequestTestRule mRule = + new PaymentRequestTestRule("show_promise/digital_goods.html", this); + + @Override + public void onMainActivityStarted() + throws InterruptedException, ExecutionException, TimeoutException {} + + @Test + @MediumTest + @Feature({"Payments"}) + public void testDigitalGoodsFastApp() + throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.IMMEDIATE_RESPONSE); + mRule.openPage(); + mRule.executeJavaScriptAndWaitForResult("create();"); + mRule.triggerUIAndWait(mRule.getReadyToPay()); + + Assert.assertEquals("USD $1.00", mRule.getOrderSummaryTotal()); + + mRule.clickAndWait(R.id.button_primary, mRule.getDismissed()); + + mRule.expectResultContains(new String[] {"\"total\":\"1.00\""}); + } + + @Test + @MediumTest + @Feature({"Payments"}) + public void testDigitalGoodsSlowApp() + throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.DELAYED_RESPONSE, PaymentRequestTestRule.DELAYED_CREATION); + mRule.openPage(); + mRule.executeJavaScriptAndWaitForResult("create();"); + mRule.triggerUIAndWait(mRule.getReadyToPay()); + + Assert.assertEquals("USD $1.00", mRule.getOrderSummaryTotal()); + + mRule.clickAndWait(R.id.button_primary, mRule.getDismissed()); + + mRule.expectResultContains(new String[] {"\"total\":\"1.00\""}); + } + + @Test + @MediumTest + @Feature({"Payments"}) + public void testSkipUIFastApp() + throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.IMMEDIATE_RESPONSE); + mRule.openPage(); + mRule.executeJavaScriptAndWaitForResult("create();"); + mRule.enableSkipUIForBasicCard(); + + mRule.openPageAndClickNodeAndWait("buy", mRule.getDismissed()); + + mRule.expectResultContains(new String[] {"\"total\":\"1.00\""}); + } + + @Test + @MediumTest + @Feature({"Payments"}) + public void testSkipUISlowApp() + throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.DELAYED_RESPONSE, PaymentRequestTestRule.DELAYED_CREATION); + mRule.openPage(); + mRule.executeJavaScriptAndWaitForResult("create();"); + mRule.enableSkipUIForBasicCard(); + + mRule.openPageAndClickNodeAndWait("buy", mRule.getDismissed()); + + mRule.expectResultContains(new String[] {"\"total\":\"1.00\""}); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseInvalidDetailsTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseInvalidDetailsTest.java new file mode 100644 index 0000000..8276c2cd --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseInvalidDetailsTest.java
@@ -0,0 +1,49 @@ +// Copyright 2019 The Chromium 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.payments; + +import android.support.test.filters.MediumTest; + +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ui.DisableAnimationsTestRule; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * A payment integration test for the show promise that resolves with invalid details. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +public class PaymentRequestShowPromiseInvalidDetailsTest implements MainActivityStartCallback { + // Disable animations to reduce flakiness. + @ClassRule + public static DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule(); + + @Rule + public PaymentRequestTestRule mRule = + new PaymentRequestTestRule("show_promise/invalid_details.html", this); + + @Override + public void onMainActivityStarted() + throws InterruptedException, ExecutionException, TimeoutException {} + + @Test + @MediumTest + @Feature({"Payments"}) + public void testReject() throws InterruptedException, ExecutionException, TimeoutException { + mRule.openPageAndClickNodeAndWait("buy", mRule.getDismissed()); + mRule.expectResultContains(new String[] {"Total amount value should be non-negative"}); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseRejectTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseRejectTest.java new file mode 100644 index 0000000..14c3932 --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseRejectTest.java
@@ -0,0 +1,51 @@ +// Copyright 2019 The Chromium 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.payments; + +import android.support.test.filters.MediumTest; + +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ui.DisableAnimationsTestRule; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * A payment integration test for the show promise that is rejected. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +public class PaymentRequestShowPromiseRejectTest implements MainActivityStartCallback { + // Disable animations to reduce flakiness. + @ClassRule + public static DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule(); + + @Rule + public PaymentRequestTestRule mRule = + new PaymentRequestTestRule("show_promise/reject.html", this); + + @Override + public void onMainActivityStarted() + throws InterruptedException, ExecutionException, TimeoutException {} + + @Test + @MediumTest + @Feature({"Payments"}) + public void testReject() throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.IMMEDIATE_RESPONSE); + mRule.openPageAndClickNodeAndWait("buy", mRule.getDismissed()); + mRule.expectResultContains(new String[] {"AbortError"}); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseSingleOptionShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseSingleOptionShippingTest.java new file mode 100644 index 0000000..0cb7fea --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseSingleOptionShippingTest.java
@@ -0,0 +1,85 @@ +// Copyright 2019 The Chromium 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.payments; + +import android.support.test.filters.MediumTest; + +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.autofill.AutofillTestHelper; +import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; +import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ui.DisableAnimationsTestRule; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * A payment integration test for the show promise with a single pre-selected shipping option and no + * shipping address change handler. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +public class PaymentRequestShowPromiseSingleOptionShippingTest + implements MainActivityStartCallback { + // Disable animations to reduce flakiness. + @ClassRule + public static DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule(); + + @Rule + public PaymentRequestTestRule mRule = + new PaymentRequestTestRule("show_promise/single_option_shipping.html", this); + + @Override + public void onMainActivityStarted() + throws InterruptedException, ExecutionException, TimeoutException { + AutofillTestHelper autofillTestHelper = new AutofillTestHelper(); + autofillTestHelper.setProfile(new AutofillProfile("", "https://example.com", true, + "Jon Doe", "Google", "340 Main St", "California", "Los Angeles", "", "90291", "", + "US", "555-222-2222", "", "en-US")); + autofillTestHelper.setProfile(new AutofillProfile("", "https://example.com", true, + "Jane Smith", "Google", "340 Main St", "California", "Los Angeles", "", "90291", "", + "US", "555-111-1111", "", "en-US")); + } + + @Test + @MediumTest + @Feature({"Payments"}) + public void testFastApp() throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.IMMEDIATE_RESPONSE); + mRule.triggerUIAndWait(mRule.getReadyToPay()); + Assert.assertEquals("USD $1.00", mRule.getOrderSummaryTotal()); + Assert.assertEquals("$0.00", mRule.getShippingOptionCostSummaryOnBottomSheet()); + mRule.clickInShippingAddressAndWait(R.id.payments_section, mRule.getReadyForInput()); + mRule.clickOnShippingAddressSuggestionOptionAndWait(1, mRule.getReadyForInput()); + mRule.clickAndWait(R.id.button_primary, mRule.getDismissed()); + mRule.expectResultContains(new String[] {"\"total\":\"1.00\""}); + } + + @Test + @MediumTest + @Feature({"Payments"}) + public void testSlowApp() throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.DELAYED_RESPONSE, PaymentRequestTestRule.DELAYED_CREATION); + mRule.triggerUIAndWait(mRule.getReadyToPay()); + Assert.assertEquals("USD $1.00", mRule.getOrderSummaryTotal()); + Assert.assertEquals("$0.00", mRule.getShippingOptionCostSummaryOnBottomSheet()); + mRule.clickInShippingAddressAndWait(R.id.payments_section, mRule.getReadyForInput()); + mRule.clickOnShippingAddressSuggestionOptionAndWait(1, mRule.getReadyForInput()); + mRule.clickAndWait(R.id.button_primary, mRule.getDismissed()); + mRule.expectResultContains(new String[] {"\"total\":\"1.00\""}); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseSingleOptionShippingWithUpdateTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseSingleOptionShippingWithUpdateTest.java new file mode 100644 index 0000000..3b8cedf --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseSingleOptionShippingWithUpdateTest.java
@@ -0,0 +1,85 @@ +// Copyright 2019 The Chromium 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.payments; + +import android.support.test.filters.MediumTest; + +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.autofill.AutofillTestHelper; +import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; +import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ui.DisableAnimationsTestRule; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * A payment integration test for the show promise with a single pre-selected shipping option and a + * shipping address change handler. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +public class PaymentRequestShowPromiseSingleOptionShippingWithUpdateTest + implements MainActivityStartCallback { + // Disable animations to reduce flakiness. + @ClassRule + public static DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule(); + + @Rule + public PaymentRequestTestRule mRule = new PaymentRequestTestRule( + "show_promise/single_option_shipping_with_update.html", this); + + @Override + public void onMainActivityStarted() + throws InterruptedException, ExecutionException, TimeoutException { + AutofillTestHelper autofillTestHelper = new AutofillTestHelper(); + autofillTestHelper.setProfile(new AutofillProfile("", "https://example.com", true, + "Jon Doe", "Google", "340 Main St", "California", "Los Angeles", "", "90291", "", + "US", "555-222-2222", "", "en-US")); + autofillTestHelper.setProfile(new AutofillProfile("", "https://example.com", true, + "Jane Smith", "Google", "340 Main St", "California", "Los Angeles", "", "90291", "", + "US", "555-111-1111", "", "en-US")); + } + + @Test + @MediumTest + @Feature({"Payments"}) + public void testFastApp() throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.IMMEDIATE_RESPONSE); + mRule.triggerUIAndWait(mRule.getReadyToPay()); + Assert.assertEquals("USD $1.00", mRule.getOrderSummaryTotal()); + Assert.assertEquals("$0.00", mRule.getShippingOptionCostSummaryOnBottomSheet()); + mRule.clickInShippingAddressAndWait(R.id.payments_section, mRule.getReadyForInput()); + mRule.clickOnShippingAddressSuggestionOptionAndWait(1, mRule.getReadyForInput()); + mRule.clickAndWait(R.id.button_primary, mRule.getDismissed()); + mRule.expectResultContains(new String[] {"\"total\":\"1.00\""}); + } + + @Test + @MediumTest + @Feature({"Payments"}) + public void testSlowApp() throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.DELAYED_RESPONSE, PaymentRequestTestRule.DELAYED_CREATION); + mRule.triggerUIAndWait(mRule.getReadyToPay()); + Assert.assertEquals("USD $1.00", mRule.getOrderSummaryTotal()); + Assert.assertEquals("$0.00", mRule.getShippingOptionCostSummaryOnBottomSheet()); + mRule.clickInShippingAddressAndWait(R.id.payments_section, mRule.getReadyForInput()); + mRule.clickOnShippingAddressSuggestionOptionAndWait(1, mRule.getReadyForInput()); + mRule.clickAndWait(R.id.button_primary, mRule.getDismissed()); + mRule.expectResultContains(new String[] {"\"total\":\"1.00\""}); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseUSOnlyShippingTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseUSOnlyShippingTest.java new file mode 100644 index 0000000..a2cb36d --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseUSOnlyShippingTest.java
@@ -0,0 +1,122 @@ +// Copyright 2019 The Chromium 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.payments; + +import android.support.test.filters.MediumTest; + +import org.junit.Assert; +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.R; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.autofill.AutofillTestHelper; +import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; +import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ui.DisableAnimationsTestRule; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * A payment integration test for the show promise with restricted shipping rules. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +public class PaymentRequestShowPromiseUSOnlyShippingTest implements MainActivityStartCallback { + // Disable animations to reduce flakiness. + @ClassRule + public static DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule(); + + @Rule + public PaymentRequestTestRule mRule = + new PaymentRequestTestRule("show_promise/us_only_shipping.html", this); + + @Override + public void onMainActivityStarted() + throws InterruptedException, ExecutionException, TimeoutException {} + + @Test + @MediumTest + @Feature({"Payments"}) + public void testCannotShipWithFastApp() + throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.IMMEDIATE_RESPONSE); + runCannotShipTest(); + } + + @Test + @MediumTest + @Feature({"Payments"}) + public void testCannotShipWithSlowApp() + throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.DELAYED_RESPONSE, PaymentRequestTestRule.DELAYED_CREATION); + runCannotShipTest(); + } + + private void runCannotShipTest() + throws InterruptedException, ExecutionException, TimeoutException { + AutofillTestHelper autofillTestHelper = new AutofillTestHelper(); + autofillTestHelper.setProfile(new AutofillProfile("", "https://example.com", true, + "Jon Doe", "Google", "51 Breithaupt St", "ON", "Kitchener", "", "N2H 5G5", "", "CA", + "555-222-2222", "", "en-CA")); + mRule.triggerUIAndWait(mRule.getReadyForInput()); + Assert.assertEquals("USD $1.00", mRule.getOrderSummaryTotal()); + mRule.clickInShippingAddressAndWait(R.id.payments_section, mRule.getReadyForInput()); + Assert.assertEquals("To see shipping methods and requirements, select an address", + mRule.getShippingAddressDescriptionLabel()); + Assert.assertEquals(null, mRule.getShippingAddressWarningLabel()); + mRule.clickOnShippingAddressSuggestionOptionAndWait(0, mRule.getReadyForInput()); + Assert.assertEquals(null, mRule.getShippingAddressDescriptionLabel()); + Assert.assertEquals("Cannot ship outside of US.", mRule.getShippingAddressWarningLabel()); + mRule.clickAndWait(R.id.button_secondary, mRule.getDismissed()); + } + + @Test + @MediumTest + @Feature({"Payments"}) + public void testCanShipWithFastApp() + throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.IMMEDIATE_RESPONSE); + runCanShipTest(); + } + + @Test + @MediumTest + @Feature({"Payments"}) + public void testCanShipWithSlowApp() + throws InterruptedException, ExecutionException, TimeoutException { + mRule.installPaymentApp("basic-card", PaymentRequestTestRule.HAVE_INSTRUMENTS, + PaymentRequestTestRule.DELAYED_RESPONSE, PaymentRequestTestRule.DELAYED_CREATION); + runCanShipTest(); + } + + private void runCanShipTest() + throws InterruptedException, ExecutionException, TimeoutException { + AutofillTestHelper autofillTestHelper = new AutofillTestHelper(); + autofillTestHelper.setProfile(new AutofillProfile("", "https://example.com", true, + "Jane Smith", "Google", "340 Main St", "California", "Los Angeles", "", "90291", "", + "US", "555-111-1111", "", "en-US")); + mRule.triggerUIAndWait(mRule.getReadyForInput()); + Assert.assertEquals("USD $1.00", mRule.getOrderSummaryTotal()); + mRule.clickInShippingAddressAndWait(R.id.payments_section, mRule.getReadyForInput()); + Assert.assertEquals("To see shipping methods and requirements, select an address", + mRule.getShippingAddressDescriptionLabel()); + Assert.assertEquals(null, mRule.getShippingAddressWarningLabel()); + mRule.clickOnShippingAddressSuggestionOptionAndWait(0, mRule.getReadyToPay()); + Assert.assertEquals(null, mRule.getShippingAddressDescriptionLabel()); + Assert.assertEquals(null, mRule.getShippingAddressWarningLabel()); + mRule.clickAndWait(R.id.button_primary, mRule.getDismissed()); + mRule.expectResultContains(new String[] {"\"total\":\"1.00\""}); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseUnsupportedTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseUnsupportedTest.java new file mode 100644 index 0000000..4e34e1c --- /dev/null +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestShowPromiseUnsupportedTest.java
@@ -0,0 +1,50 @@ +// Copyright 2019 The Chromium 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.payments; + +import android.support.test.filters.MediumTest; + +import org.junit.ClassRule; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.Feature; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.payments.PaymentRequestTestRule.MainActivityStartCallback; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.chrome.test.ui.DisableAnimationsTestRule; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeoutException; + +/** + * A payment integration test for the show promise with an unsupported payment method. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) +public class PaymentRequestShowPromiseUnsupportedTest implements MainActivityStartCallback { + // Disable animations to reduce flakiness. + @ClassRule + public static DisableAnimationsTestRule sNoAnimationsRule = new DisableAnimationsTestRule(); + + @Rule + public PaymentRequestTestRule mRule = + new PaymentRequestTestRule("show_promise/unsupported.html", this); + + @Override + public void onMainActivityStarted() + throws InterruptedException, ExecutionException, TimeoutException {} + + @Test + @MediumTest + @Feature({"Payments"}) + public void testReject() throws InterruptedException, ExecutionException, TimeoutException { + mRule.openPageAndClickNodeAndWait("buy", mRule.getDismissed()); + mRule.expectResultContains( + new String[] {"NotSupportedError: The payment method \"foo\" is not supported"}); + } +}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java index 42ca009..c6329db 100644 --- a/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java +++ b/chrome/android/javatests/src/org/chromium/chrome/browser/payments/PaymentRequestTestRule.java
@@ -12,6 +12,7 @@ import android.widget.CheckBox; import android.widget.EditText; import android.widget.Spinner; +import android.widget.TextView; import org.junit.Assert; import org.junit.runner.Description; @@ -117,6 +118,7 @@ final CallbackHelper mHasEnrolledInstrumentQueryResponded; final CallbackHelper mExpirationMonthChange; final CallbackHelper mPaymentResponseReady; + PaymentRequestImpl mPaymentRequest; PaymentRequestUI mUI; private final AtomicReference<WebContents> mWebContentsRef; @@ -163,7 +165,7 @@ startMainActivityWithURL(mTestFilePath); } - private void openPage() throws InterruptedException, ExecutionException, TimeoutException { + protected void openPage() throws InterruptedException, ExecutionException, TimeoutException { onMainActivityStarted(); ThreadUtils.runOnUiThreadBlocking(() -> { mWebContentsRef.set(getActivity().getCurrentWebContents()); @@ -277,6 +279,11 @@ helper.waitForCallback(callCount); } + protected String executeJavaScriptAndWaitForResult(String script) + throws InterruptedException, TimeoutException { + return JavaScriptUtils.executeJavaScriptAndWaitForResult(mWebContentsRef.get(), script); + } + /** Clicks on an HTML node. */ protected void clickNodeAndWait(String nodeId, CallbackHelper helper) throws InterruptedException, TimeoutException { @@ -494,6 +501,24 @@ .toString()); } + protected String getShippingAddressWarningLabel() throws ExecutionException { + return ThreadUtils.runOnUiThreadBlocking(() -> { + View view = mUI.getShippingAddressSectionForTest().findViewById( + R.id.payments_warning_label); + return view != null && view instanceof TextView ? ((TextView) view).getText().toString() + : null; + }); + } + + protected String getShippingAddressDescriptionLabel() throws ExecutionException { + return ThreadUtils.runOnUiThreadBlocking(() -> { + View view = mUI.getShippingAddressSectionForTest().findViewById( + R.id.payments_description_label); + return view != null && view instanceof TextView ? ((TextView) view).getText().toString() + : null; + }); + } + /** Returns the focused view in the card editor view. */ protected View getCardEditorFocusedView() { return mUI.getCardEditorDialog().getCurrentFocus(); @@ -767,8 +792,8 @@ } for (int i = 0; i < contents.length; i++) { if (!result.contains(contents[i])) { - updateFailureReason( - String.format("Result should contain '%s'", contents[i])); + updateFailureReason(String.format( + "Result '" + result + "' should contain '%s'", contents[i])); return false; } } @@ -864,6 +889,12 @@ .findViewById(R.id.autofill_card_unmask_prompt)); } + /** Allows to skip UI into paymenthandler for"basic-card". */ + protected void enableSkipUIForBasicCard() { + ThreadUtils.runOnUiThreadBlocking( + () -> mPaymentRequest.setSkipUIForNonURLPaymentMethodIdentifiersForTest()); + } + @Override public void onPaymentRequestReadyForInput(PaymentRequestUI ui) { ThreadUtils.assertOnUiThread(); @@ -913,6 +944,12 @@ } @Override + public void onPaymentRequestCreated(PaymentRequestImpl paymentRequest) { + ThreadUtils.assertOnUiThread(); + mPaymentRequest = paymentRequest; + } + + @Override public void onPaymentRequestServiceUnableToAbort() { ThreadUtils.assertOnUiThread(); mUnableToAbort.notifyCalled(); @@ -1137,7 +1174,8 @@ Map<String, PaymentMethodData> methodData, PaymentItem total, List<PaymentItem> displayItems, Map<String, PaymentDetailsModifier> modifiers, InstrumentDetailsCallback detailsCallback) { - detailsCallback.onInstrumentDetailsReady(mDefaultMethodName, "{\"transaction\": 1337}"); + detailsCallback.onInstrumentDetailsReady(mDefaultMethodName, + "{\"transaction\": 1337, \"total\": \"" + total.amount.value + "\"}"); } @Override
diff --git a/chrome/app/vr_strings.grdp b/chrome/app/vr_strings.grdp index 68aa53a..1c4c5704 100644 --- a/chrome/app/vr_strings.grdp +++ b/chrome/app/vr_strings.grdp
@@ -26,6 +26,12 @@ <message name="IDS_VR_SHELL_SITE_IS_SHARING_SCREEN" desc="Text displayed in a transient bubble to inform the user that the page is sharing the screen."> Site is sharing your screen </message> + <message name="IDS_VR_SHELL_SITE_IS_USING_USB" desc="Text displayed in a transient bubble to inform the user that the page is using a usb device."> + Site is using usb + </message> + <message name="IDS_VR_SHELL_SITE_IS_USING_MIDI" desc="Text displayed in a transient bubble to inform the user that the page is using a midi device."> + Site is using midi + </message> <message name="IDS_VR_SHELL_BG_IS_USING_MICROPHONE" desc="Text displayed in a transient bubble to inform the user that a background tab is using the microphone."> Background tab is using your microphone </message> @@ -53,6 +59,9 @@ <message name="IDS_VR_SHELL_SITE_CAN_SHARE_SCREEN" desc="Text displayed in a transient bubble to inform the user that the page may share your screen, but isn't doing so yet."> Site can share your screen </message> + <message name="IDS_VR_SHELL_SITE_CAN_USE_MIDI" desc="Text displayed in a transient bubble to inform the user that the page may use midi, but isn't doing so yet."> + Site can use midi + </message> <!-- Desktop-specific permission prompts --> <if expr="not is_android">
diff --git a/chrome/app/vr_strings_grdp/IDS_VR_SHELL_SITE_CAN_USE_MIDI.png.sha1 b/chrome/app/vr_strings_grdp/IDS_VR_SHELL_SITE_CAN_USE_MIDI.png.sha1 new file mode 100644 index 0000000..ef811f7 --- /dev/null +++ b/chrome/app/vr_strings_grdp/IDS_VR_SHELL_SITE_CAN_USE_MIDI.png.sha1
@@ -0,0 +1 @@ +08cc406f5af3268f88635fac97a8211cc2acad7b \ No newline at end of file
diff --git a/chrome/app/vr_strings_grdp/IDS_VR_SHELL_SITE_IS_USING_MIDI.png.sha1 b/chrome/app/vr_strings_grdp/IDS_VR_SHELL_SITE_IS_USING_MIDI.png.sha1 new file mode 100644 index 0000000..b856cb34 --- /dev/null +++ b/chrome/app/vr_strings_grdp/IDS_VR_SHELL_SITE_IS_USING_MIDI.png.sha1
@@ -0,0 +1 @@ +2f29233562df49efae82df0b7850f8fccfdf0db5 \ No newline at end of file
diff --git a/chrome/app/vr_strings_grdp/IDS_VR_SHELL_SITE_IS_USING_USB.png.sha1 b/chrome/app/vr_strings_grdp/IDS_VR_SHELL_SITE_IS_USING_USB.png.sha1 new file mode 100644 index 0000000..0530f2b0 --- /dev/null +++ b/chrome/app/vr_strings_grdp/IDS_VR_SHELL_SITE_IS_USING_USB.png.sha1
@@ -0,0 +1 @@ +0670fbaa8bd7f1d36f9dce06ea233f40c25d4486 \ No newline at end of file
diff --git a/chrome/browser/apps/app_service/app_icon_factory.cc b/chrome/browser/apps/app_service/app_icon_factory.cc index 4bc5834..d86de71 100644 --- a/chrome/browser/apps/app_service/app_icon_factory.cc +++ b/chrome/browser/apps/app_service/app_icon_factory.cc
@@ -17,8 +17,11 @@ #include "chrome/browser/extensions/chrome_app_icon_loader.h" #include "chrome/browser/extensions/extension_service.h" #include "content/public/common/service_manager_connection.h" +#include "extensions/browser/component_extension_resource_manager.h" #include "extensions/browser/extension_system.h" +#include "extensions/browser/extensions_browser_client.h" #include "extensions/browser/image_loader.h" +#include "extensions/common/manifest.h" #include "extensions/common/manifest_handlers/icons_handler.h" #include "services/data_decoder/public/cpp/decode_image.h" #include "ui/base/resource/resource_bundle.h" @@ -219,13 +222,42 @@ } case apps::mojom::IconCompression::kCompressed: { - base::PostTaskWithTraitsAndReplyWithResult( - FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, - base::BindOnce(&CompressedDataFromResource, ext_resource), - base::BindOnce(&RunCallbackWithCompressedData, size_hint_in_dip, - is_placeholder_icon, icon_effects, - std::move(callback))); - return; + // Load component extensions' icons from statically compiled resources + // (built into the Chrome binary), and other extensions' icons from + // files on disk. + // + // For the kUncompressed case above, RunCallbackWithUncompressedImage + // calls extensions::ImageLoader::LoadImageAsync, which already handles + // that distinction. We can't use LoadImageAsync here, because the + // caller has asked for compressed icons (i.e. PNG-formatted data), not + // uncompressed (i.e. a gfx::ImageSkia). + if (extension->location() == extensions::Manifest::COMPONENT) { + extensions::ComponentExtensionResourceInfo resource_info; + const extensions::ComponentExtensionResourceManager* manager = + extensions::ExtensionsBrowserClient::Get() + ->GetComponentExtensionResourceManager(); + if (manager && manager->IsComponentExtensionResource( + extension->path(), ext_resource.relative_path(), + &resource_info)) { + base::StringPiece data = + ui::ResourceBundle::GetSharedInstance().GetRawDataResource( + resource_info.resource_id); + RunCallbackWithCompressedData( + size_hint_in_dip, is_placeholder_icon, icon_effects, + std::move(callback), + std::vector<uint8_t>(data.begin(), data.end())); + return; + } + } else if (!ext_resource.GetFilePath().empty()) { + base::PostTaskWithTraitsAndReplyWithResult( + FROM_HERE, {base::MayBlock(), base::TaskPriority::USER_VISIBLE}, + base::BindOnce(&CompressedDataFromResource, + std::move(ext_resource)), + base::BindOnce(&RunCallbackWithCompressedData, size_hint_in_dip, + is_placeholder_icon, icon_effects, + std::move(callback))); + return; + } } } }
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc index 07f77d8..2d84d7c 100644 --- a/chrome/browser/apps/app_service/extension_apps.cc +++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -120,6 +120,8 @@ apps::mojom::Readiness::kTerminated, &apps); // blacklisted_extensions and blocked_extensions, corresponding to // kDisabledByBlacklist and kDisabledByPolicy, are deliberately ignored. + // + // If making changes to which sets are consulted, also change ShouldShow. } subscriber->OnApps(std::move(apps)); subscribers_.AddPtr(std::move(subscriber)); @@ -329,6 +331,7 @@ app->app_id = extension->id(); app->readiness = apps::mojom::Readiness::kUninstalledByUser; + SetShowInFields(app, extension, profile_); Publish(std::move(app)); } @@ -363,6 +366,42 @@ } // static +void ExtensionApps::SetShowInFields(apps::mojom::AppPtr& app, + const extensions::Extension* extension, + Profile* profile) { + if (ShouldShow(extension, profile)) { + auto show = app_list::ShouldShowInLauncher(extension, profile) + ? apps::mojom::OptionalBool::kTrue + : apps::mojom::OptionalBool::kFalse; + app->show_in_launcher = show; + app->show_in_search = show; + app->show_in_management = ShouldShowInAppManagement(extension); + } else { + app->show_in_launcher = apps::mojom::OptionalBool::kFalse; + app->show_in_search = apps::mojom::OptionalBool::kFalse; + app->show_in_management = apps::mojom::OptionalBool::kFalse; + } +} + +// static +bool ExtensionApps::ShouldShow(const extensions::Extension* extension, + Profile* profile) { + if (!profile) { + return false; + } + + extensions::ExtensionRegistry* registry = + extensions::ExtensionRegistry::Get(profile); + const std::string& app_id = extension->id(); + // These three extension sets are the same three consulted by Connect. + // Importantly, it will exclude previously installed but currently + // uninstalled extensions. + return registry->enabled_extensions().Contains(app_id) || + registry->disabled_extensions().Contains(app_id) || + registry->terminated_extensions().Contains(app_id); +} + +// static apps::mojom::OptionalBool ExtensionApps::ShouldShowInAppManagement( const extensions::Extension* extension) { // Component extensions should not show up in App Management as they @@ -473,13 +512,7 @@ ? apps::mojom::OptionalBool::kTrue : apps::mojom::OptionalBool::kFalse; - auto show = app_list::ShouldShowInLauncher(extension, profile_) - ? apps::mojom::OptionalBool::kTrue - : apps::mojom::OptionalBool::kFalse; - app->show_in_launcher = show; - app->show_in_search = show; - app->show_in_management = ShouldShowInAppManagement(extension); - + SetShowInFields(app, extension, profile_); return app; }
diff --git a/chrome/browser/apps/app_service/extension_apps.h b/chrome/browser/apps/app_service/extension_apps.h index 76ef9819..4f0e98ea 100644 --- a/chrome/browser/apps/app_service/extension_apps.h +++ b/chrome/browser/apps/app_service/extension_apps.h
@@ -88,8 +88,15 @@ bool RunExtensionEnableFlow(const std::string& app_id); static bool IsBlacklisted(const std::string& app_id); + + static void SetShowInFields(apps::mojom::AppPtr& app, + const extensions::Extension* extension, + Profile* profile); + static bool ShouldShow(const extensions::Extension* extension, + Profile* profile); static apps::mojom::OptionalBool ShouldShowInAppManagement( const extensions::Extension* extension); + void PopulatePermissions(const extensions::Extension* extension, std::vector<mojom::PermissionPtr>* target); apps::mojom::AppPtr Convert(const extensions::Extension* extension,
diff --git a/chrome/browser/chromeos/printing/printer_configurer.cc b/chrome/browser/chromeos/printing/printer_configurer.cc index afc94072..f105392d 100644 --- a/chrome/browser/chromeos/printing/printer_configurer.cc +++ b/chrome/browser/chromeos/printing/printer_configurer.cc
@@ -23,7 +23,6 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chromeos/printing/ppd_provider_factory.h" #include "chrome/browser/component_updater/cros_component_installer_chromeos.h" -#include "chrome/browser/local_discovery/endpoint_resolver.h" #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_features.h" #include "chromeos/dbus/dbus_thread_manager.h" @@ -32,8 +31,6 @@ #include "chromeos/printing/printer_configuration.h" #include "components/device_event_log/device_event_log.h" #include "content/public/browser/browser_thread.h" -#include "net/base/host_port_pair.h" -#include "net/base/ip_endpoint.h" #include "third_party/cros_system_api/dbus/debugd/dbus-constants.h" const std::map<const std::string, const std::string>& @@ -103,9 +100,7 @@ class PrinterConfigurerImpl : public PrinterConfigurer { public: explicit PrinterConfigurerImpl(Profile* profile) - : endpoint_resolver_(new local_discovery::EndpointResolver()), - ppd_provider_(CreatePpdProvider(profile)), - weak_factory_(this) {} + : ppd_provider_(CreatePpdProvider(profile)), weak_factory_(this) {} PrinterConfigurerImpl(const PrinterConfigurerImpl&) = delete; PrinterConfigurerImpl& operator=(const PrinterConfigurerImpl&) = delete; @@ -118,36 +113,6 @@ DCHECK(!printer.id().empty()); DCHECK(!printer.uri().empty()); PRINTER_LOG(USER) << printer.make_and_model() << " Printer setup requested"; - - // Ensure that |address| is non-empty before attempting to resolve it. - // If the uri in |printer| does not contain both a hostname and a port - // number then GetHostAndPort() will return an empty string. - auto address = printer.GetHostAndPort(); - if (address.IsEmpty()) { - // Return an error and abort printer setup. If we attempt to call - // EndpointResolver::Start() with an empty address then it will fail - // silently without returning into the callback. - PRINTER_LOG(ERROR) << "Address is invalid"; - std::move(callback).Run(PrinterSetupResult::kPrinterUnreachable); - return; - } - - PRINTER_LOG(DEBUG) << printer.make_and_model() - << " Resolving IP: " << address.ToString(); - - // Resolve the uri to an ip with a mutable copy of the printer. - endpoint_resolver_->Start( - address, base::BindOnce(&PrinterConfigurerImpl::OnIpResolved, - weak_factory_.GetWeakPtr(), - std::make_unique<Printer>(printer), - std::move(callback))); - } - - private: - // Run installation for a printer with a resolved uri. |callback| is called - // with the result of the setup when it is complete. - void StartConfiguration(const Printer& printer, - PrinterSetupCallback callback) { if (!printer.IsIppEverywhere()) { PRINTER_LOG(DEBUG) << printer.make_and_model() << " Lookup PPD"; ppd_provider_->ResolvePpd( @@ -168,29 +133,7 @@ std::move(callback))); } - // Callback for when the IP for a zeroconf printer has been resolved. If the - // request was successful, sets the |effective_uri| on |printer| with - // |endpoint| then continues setup. |cb| is called with a result reporting the - // success or failure of the setup operation, eventually. - void OnIpResolved(std::unique_ptr<Printer> printer, - PrinterSetupCallback cb, - const net::IPEndPoint& endpoint) { - bool address_resolved = endpoint.address().IsValid(); - UMA_HISTOGRAM_BOOLEAN("Printing.CUPS.AddressResolutionResult", - address_resolved); - if (!address_resolved) { - PRINTER_LOG(ERROR) << printer->make_and_model() - << " IP Resolution failed"; - // |endpoint| does not have a valid address. Address was not resolved. - std::move(cb).Run(kPrinterUnreachable); - return; - } - - PRINTER_LOG(EVENT) << printer->make_and_model() - << " IP Resolution succeeded"; - StartConfiguration(*printer, std::move(cb)); - } - + private: // Receive the callback from the debug daemon client once we attempt to // add the printer. void OnAddedPrinter(const Printer& printer, @@ -296,7 +239,6 @@ } } - std::unique_ptr<local_discovery::EndpointResolver> endpoint_resolver_; scoped_refptr<PpdProvider> ppd_provider_; base::WeakPtrFactory<PrinterConfigurerImpl> weak_factory_; };
diff --git a/chrome/browser/extensions/api/cast_streaming/performance_test.cc b/chrome/browser/extensions/api/cast_streaming/performance_test.cc index 8d3d46c..03a5a0e5 100644 --- a/chrome/browser/extensions/api/cast_streaming/performance_test.cc +++ b/chrome/browser/extensions/api/cast_streaming/performance_test.cc
@@ -67,13 +67,13 @@ // long enough to collect sufficient tracing data; and, unfortunately, there's // nothing we can do about that. #define EXPECT_FOR_PERFORMANCE_RUN(expr) \ - do { \ + if (!(expr)) { \ if (is_full_performance_run()) { \ - EXPECT_TRUE(expr); \ - } else if (!(expr)) { \ + LOG(ERROR) << "Failure: " << #expr; \ + } else { \ LOG(WARNING) << "Allowing failure: " << #expr; \ } \ - } while (false) + } enum TestFlags { kSmallWindow = 1 << 2, // Window size: 1 = 800x600, 0 = 2000x1000 @@ -168,7 +168,7 @@ const std::string& modifier, const std::string& trace, const std::string& unit) { - if (num_values_ >= 20) { + if (num_values_ > 0) { perf_test::PrintResultMeanAndError(measurement, modifier, trace, @@ -176,8 +176,7 @@ unit, true); } else { - LOG(ERROR) << "Not enough events (" << num_values_ << ") for " - << measurement << modifier << " " << trace; + LOG(ERROR) << "No events for " << measurement << modifier << " " << trace; } }
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc b/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc index 7b455d2..fe7bf28a2 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.cc
@@ -22,6 +22,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/test/base/tracing.h" #include "chrome/test/base/ui_test_utils.h" +#include "content/public/common/content_features.h" #include "content/public/test/browser_test_utils.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" @@ -32,6 +33,7 @@ #include "net/test/embedded_test_server/embedded_test_server.h" #include "net/test/embedded_test_server/http_request.h" #include "net/test/embedded_test_server/http_response.h" +#include "services/service_manager/sandbox/features.h" #include "third_party/zlib/google/compression_utils.h" #include "ui/gl/gl_switches.h" @@ -47,6 +49,15 @@ // Because screen capture is involved, require pixel output. EnablePixelOutput(); + feature_list_.InitWithFeatures( + { + service_manager::features::kAudioServiceSandbox, + features::kAudioServiceAudioStreams, + features::kAudioServiceLaunchOnStartup, + features::kAudioServiceOutOfProcess, + }, + {}); + InProcessBrowserTest::SetUp(); }
diff --git a/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.h b/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.h index 51d0fd4..8a1c7146 100644 --- a/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.h +++ b/chrome/browser/extensions/api/tab_capture/tab_capture_performance_test_base.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/strings/string_piece.h" +#include "base/test/scoped_feature_list.h" #include "base/test/trace_event_analyzer.h" #include "chrome/test/base/in_process_browser_test.h" @@ -135,6 +136,9 @@ const extensions::Extension* extension_ = nullptr; + // Manages the Audio Service feature set, enabled for these performance tests. + base::test::ScopedFeatureList feature_list_; + DISALLOW_COPY_AND_ASSIGN(TabCapturePerformanceTestBase); };
diff --git a/chrome/browser/extensions/extension_service.cc b/chrome/browser/extensions/extension_service.cc index 3b26e20..caeefb2 100644 --- a/chrome/browser/extensions/extension_service.cc +++ b/chrome/browser/extensions/extension_service.cc
@@ -1208,6 +1208,8 @@ } void ExtensionService::AddComponentExtension(const Extension* extension) { + extension_prefs_->ClearInapplicableDisableReasonsForComponentExtension( + extension->id()); const std::string old_version_string( extension_prefs_->GetVersionString(extension->id())); const base::Version old_version(old_version_string);
diff --git a/chrome/browser/notifications/proto/BUILD.gn b/chrome/browser/notifications/proto/BUILD.gn index 647f392..8e80255 100644 --- a/chrome/browser/notifications/proto/BUILD.gn +++ b/chrome/browser/notifications/proto/BUILD.gn
@@ -6,7 +6,9 @@ proto_library("proto") { sources = [ + "client_state.proto", "icon.proto", + "impression.proto", "notification_data.proto", ] }
diff --git a/chrome/browser/notifications/proto/client_state.proto b/chrome/browser/notifications/proto/client_state.proto new file mode 100644 index 0000000..666a267 --- /dev/null +++ b/chrome/browser/notifications/proto/client_state.proto
@@ -0,0 +1,52 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package notifications.proto; + +import "impression.proto"; + +// Contains details about supression and recovery after suppression expired. +// Should match SuppressionInfo in impression_types.h. +// Next tag: 4 +message SuppressionInfo { + // The suppression trigger time stamp in milliseconds since epoch. + optional int64 last_trigger_time = 1; + + // The duration for the suppression in milliseconds. + optional int64 duration_ms = 2; + + // The maximum number of notification to show after the suppression expired. + optional int32 recover_goal = 3; +} + +// Stores the global states about how often the notification can be shown +// to the user and the history of user interactions to a particular notification +// client. Should match ClientState in impression_types.h. +// Next tag: 5 +message ClientState { + // The type of clients using the notification scheduler system. + enum SchedulerClientType { + TEST_1 = -1; + TEST_2 = -2; + TEST_3 = -3; + UNKNOWN = 0; + } + + // The type of notification using the scheduler. + optional SchedulerClientType type = 1; + + // The maximum number of notifications shown to the user for this type. May + // change if the user interacts with the notification. + optional int32 current_max_daily_show = 2; + + // A list of user impression history. Sorted by creation time. + repeated Impression impressions = 3; + + // Suppression details, no value if there is currently no suppression. + optional SuppressionInfo suppression_info = 4; +}
diff --git a/chrome/browser/notifications/proto/impression.proto b/chrome/browser/notifications/proto/impression.proto new file mode 100644 index 0000000..ad61641 --- /dev/null +++ b/chrome/browser/notifications/proto/impression.proto
@@ -0,0 +1,59 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +syntax = "proto2"; + +option optimize_for = LITE_RUNTIME; + +package notifications.proto; + +// Contains data to determine when a notification should be shown to the user +// and the user impression towards this notification. Should match Impression in +// impression_types.h. +// Next tag: 6 +message Impression { + // The type of user feedback from a displayed notification. Should match + // UserFeedback in notification_scheduler_types.h. + enum UserFeedback { + NO_FEEDBACK = 0; + HELPFUL = 1; + NOT_HELPFUL = 2; + CLICK = 3; + DISMISS = 4; + IGNORE = 5; + } + + // The user impression of a particular notification. Should match + // ImpressionResult in notification_scheduler_types.h. + enum ImpressionResult { + INVALID = 0; + POSITIVE = 1; + NEGATIVE = 2; + NEUTRAL = 3; + } + + // Enum to describe the time to process scheduled notification data. Should + // match SchedulerTaskTime in internal_types.h. + enum SchedulerTaskTime { + UNKNOWN_TASK_TIME = 0; + MORNING = 1; + EVENING = 2; + } + + // Creation time stamp in milliseconds since epoch. + optional int64 create_time = 1; + + // The user feedback on the notification. + optional UserFeedback feedback = 2; + + // The impression type. + optional ImpressionResult impression = 3; + + // If the user feedback is used in computing the current notification deliver + // rate. + optional bool integrated = 4; + + // The task start time when the notification is shown. + optional SchedulerTaskTime task_start_time = 5; +}
diff --git a/chrome/browser/notifications/scheduler/icon_store.cc b/chrome/browser/notifications/scheduler/icon_store.cc index 60245c0..a228d38 100644 --- a/chrome/browser/notifications/scheduler/icon_store.cc +++ b/chrome/browser/notifications/scheduler/icon_store.cc
@@ -18,7 +18,7 @@ void ProtoToData(notifications::proto::Icon* proto, notifications::IconEntry* icon_entry) { - IconProtoToEntry(proto, icon_entry); + IconEntryFromProto(proto, icon_entry); } } // namespace leveldb_proto
diff --git a/chrome/browser/notifications/scheduler/icon_store.h b/chrome/browser/notifications/scheduler/icon_store.h index a05645b..2fece4e 100644 --- a/chrome/browser/notifications/scheduler/icon_store.h +++ b/chrome/browser/notifications/scheduler/icon_store.h
@@ -11,6 +11,7 @@ #include "base/bind.h" #include "base/callback.h" #include "base/macros.h" +#include "base/memory/weak_ptr.h" #include "chrome/browser/notifications/proto/icon.pb.h" #include "chrome/browser/notifications/scheduler/icon_entry.h" #include "components/leveldb_proto/public/proto_database.h"
diff --git a/chrome/browser/notifications/scheduler/impression_history_tracker.cc b/chrome/browser/notifications/scheduler/impression_history_tracker.cc index c482f21..286aa47 100644 --- a/chrome/browser/notifications/scheduler/impression_history_tracker.cc +++ b/chrome/browser/notifications/scheduler/impression_history_tracker.cc
@@ -70,7 +70,7 @@ break; case UserFeedback::kIgnore: break; - case UserFeedback::kUnknown: + case UserFeedback::kNoFeedback: FALLTHROUGH; default: // The user didn't interact with the notification yet.
diff --git a/chrome/browser/notifications/scheduler/impression_history_tracker_unittest.cc b/chrome/browser/notifications/scheduler/impression_history_tracker_unittest.cc index a199a4a0..fbf7af99 100644 --- a/chrome/browser/notifications/scheduler/impression_history_tracker_unittest.cc +++ b/chrome/browser/notifications/scheduler/impression_history_tracker_unittest.cc
@@ -91,10 +91,10 @@ config().impression_expiration; auto not_expired_time = base::Time::Now() + base::TimeDelta::FromDays(1) - config().impression_expiration; - Impression expired{expired_create_time, UserFeedback::kUnknown, - ImpressionResult::kUnknown, false /* integrated */}; - Impression not_expired{not_expired_time, UserFeedback::kUnknown, - ImpressionResult::kUnknown, false /* integrated */}; + Impression expired{expired_create_time, UserFeedback::kNoFeedback, + ImpressionResult::kInvalid, false /* integrated */}; + Impression not_expired{not_expired_time, UserFeedback::kNoFeedback, + ImpressionResult::kInvalid, false /* integrated */}; test_case.input = {{SchedulerClientType::kTest1, 2 /* current_max_daily_show */, @@ -120,7 +120,7 @@ test_case.input = {{SchedulerClientType::kTest1, 2 /* current_max_daily_show */, {{create_time, UserFeedback::kHelpful, - ImpressionResult::kUnknown, false /* integrated */}}, + ImpressionResult::kInvalid, false /* integrated */}}, base::nullopt /* suppression_info */}}; // Positive impression should bump |the current_max_daily_show| and update
diff --git a/chrome/browser/notifications/scheduler/impression_types.cc b/chrome/browser/notifications/scheduler/impression_types.cc index efdf022..5f9b019c 100644 --- a/chrome/browser/notifications/scheduler/impression_types.cc +++ b/chrome/browser/notifications/scheduler/impression_types.cc
@@ -27,8 +27,10 @@ duration == other.duration && recover_goal == other.recover_goal; } -ClientState::ClientState(SchedulerClientType type) - : type(type), current_max_daily_show(0) {} +ClientState::ClientState() + : type(SchedulerClientType::kUnknown), current_max_daily_show(0) {} + +ClientState::ClientState(const ClientState& other) = default; ClientState::~ClientState() = default; @@ -52,7 +54,9 @@ << "feedback: " << static_cast<int>(impression.feedback) << " \n" << "impression result: " << static_cast<int>(impression.impression) << " \n" - << "integrated: " << impression.integrated << " \n"; + << "integrated: " << impression.integrated << " \n" + << "task start time: " + << static_cast<int>(impression.task_start_time) << "\n"; log += stream.str(); }
diff --git a/chrome/browser/notifications/scheduler/impression_types.h b/chrome/browser/notifications/scheduler/impression_types.h index 53f2c31d..cd24af9 100644 --- a/chrome/browser/notifications/scheduler/impression_types.h +++ b/chrome/browser/notifications/scheduler/impression_types.h
@@ -32,12 +32,12 @@ // The user feedback on the notification, each notification will have at most // one feedback. Sets after the user interacts with the notification. - UserFeedback feedback = UserFeedback::kUnknown; + UserFeedback feedback = UserFeedback::kNoFeedback; // The impression type. The client of a notification type takes one or several // user feedbacks as input and generate a user impression, which will // eventually affect the rate to deliver notifications to the user. - ImpressionResult impression = ImpressionResult::kUnknown; + ImpressionResult impression = ImpressionResult::kInvalid; // If the user feedback is used in computing the current notification deliver // rate. @@ -71,7 +71,7 @@ // client. struct ClientState { using Impressions = std::deque<Impression>; - explicit ClientState(SchedulerClientType type); + ClientState(); explicit ClientState(const ClientState& other); ~ClientState(); @@ -81,7 +81,7 @@ std::string DebugPrint() const; // The type of notification using the scheduler. - const SchedulerClientType type; + SchedulerClientType type; // The maximum number of notifications shown to the user for this type. May // change if the user interacts with the notification.
diff --git a/chrome/browser/notifications/scheduler/notification_scheduler_types.h b/chrome/browser/notifications/scheduler/notification_scheduler_types.h index ecd65840..12b7546 100644 --- a/chrome/browser/notifications/scheduler/notification_scheduler_types.h +++ b/chrome/browser/notifications/scheduler/notification_scheduler_types.h
@@ -21,8 +21,8 @@ // The type of user feedback from a displayed notification. enum class UserFeedback { - // Unknown feedback from the user. - kUnknown = 0, + // No user feedback yet. + kNoFeedback = 0, // The user taps the helpful button, potentially a strong indicator of user's // positive preference on the notification. kHelpful = 1, @@ -40,15 +40,15 @@ // The user impression of a particular notification. enum class ImpressionResult { - // Unknown user impression. - kUnknown = 0, + // Invalid user impression. + kInvalid = 0, // Positive user impression that the user may like the notification. kPositive = 1, // Positive user impression that the user may dislike the notification. kNegative = 2, - // The feedback is netural to the user. - kNetural = 3, - kMaxValue = kNetural + // The feedback is neutral to the user. + kNeutral = 3, + kMaxValue = kNeutral }; } // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/proto_conversion.cc b/chrome/browser/notifications/scheduler/proto_conversion.cc index c42457cd..4e7c1141 100644 --- a/chrome/browser/notifications/scheduler/proto_conversion.cc +++ b/chrome/browser/notifications/scheduler/proto_conversion.cc
@@ -11,16 +11,233 @@ namespace notifications { +namespace { + +// Helper method to convert base::TimeDelta to integer for serialization. Loses +// precision beyond miliseconds. +int64_t TimeDeltaToMilliseconds(const base::TimeDelta& delta) { + return delta.InMilliseconds(); +} + +// Helper method to convert serialized time delta as integer to base::TimeDelta +// for deserialization. Loses precision beyond miliseconds. +base::TimeDelta MillisecondsToTimeDelta(int64_t serialized_delat_ms) { + return base::TimeDelta::FromMilliseconds(serialized_delat_ms); +} + +// Helper method to convert base::Time to integer for serialization. Loses +// precision beyond miliseconds. +int64_t TimeToMilliseconds(const base::Time& time) { + return time.ToDeltaSinceWindowsEpoch().InMilliseconds(); +} + +// Helper method to convert serialized time as integer to base::Time for +// deserialization. Loses precision beyond miliseconds. +base::Time MillisecondsToTime(int64_t serialized_time_ms) { + return base::Time::FromDeltaSinceWindowsEpoch( + base::TimeDelta::FromMilliseconds(serialized_time_ms)); +} + +// Converts SchedulerClientType to its associated enum in proto buffer. +proto::ClientState_SchedulerClientType ToSchedulerClientType( + SchedulerClientType type) { + switch (type) { + case SchedulerClientType::kTest1: + return proto::ClientState_SchedulerClientType_TEST_1; + case SchedulerClientType::kTest2: + return proto::ClientState_SchedulerClientType_TEST_2; + case SchedulerClientType::kTest3: + return proto::ClientState_SchedulerClientType_TEST_3; + case SchedulerClientType::kUnknown: + return proto::ClientState_SchedulerClientType_UNKNOWN; + } + NOTREACHED(); +} + +// Converts SchedulerClientType from its associated enum in proto buffer. +SchedulerClientType FromSchedulerClientType( + proto::ClientState_SchedulerClientType proto_type) { + switch (proto_type) { + case proto::ClientState_SchedulerClientType_TEST_1: + return SchedulerClientType::kTest1; + case proto::ClientState_SchedulerClientType_TEST_2: + return SchedulerClientType::kTest2; + case proto::ClientState_SchedulerClientType_TEST_3: + return SchedulerClientType::kTest3; + case proto::ClientState_SchedulerClientType_UNKNOWN: + return SchedulerClientType::kUnknown; + } + NOTREACHED(); +} + +// Converts UserFeedback to its associated enum in proto buffer. +proto::Impression_UserFeedback ToUserFeedback(UserFeedback feedback) { + switch (feedback) { + case UserFeedback::kNoFeedback: + return proto::Impression_UserFeedback_NO_FEEDBACK; + case UserFeedback::kHelpful: + return proto::Impression_UserFeedback_HELPFUL; + case UserFeedback::kNotHelpful: + return proto::Impression_UserFeedback_NOT_HELPFUL; + case UserFeedback::kClick: + return proto::Impression_UserFeedback_CLICK; + case UserFeedback::kDismiss: + return proto::Impression_UserFeedback_DISMISS; + case UserFeedback::kIgnore: + return proto::Impression_UserFeedback_IGNORE; + } + NOTREACHED(); +} + +// Converts UserFeedback from its associated enum in proto buffer. +UserFeedback FromUserFeedback(proto::Impression_UserFeedback feedback) { + switch (feedback) { + case proto::Impression_UserFeedback_NO_FEEDBACK: + return UserFeedback::kNoFeedback; + case proto::Impression_UserFeedback_HELPFUL: + return UserFeedback::kHelpful; + case proto::Impression_UserFeedback_NOT_HELPFUL: + return UserFeedback::kNotHelpful; + case proto::Impression_UserFeedback_CLICK: + return UserFeedback::kClick; + case proto::Impression_UserFeedback_DISMISS: + return UserFeedback::kDismiss; + case proto::Impression_UserFeedback_IGNORE: + return UserFeedback::kIgnore; + } + NOTREACHED(); +} + +// Converts ImpressionResult to its associated enum in proto buffer. +proto::Impression_ImpressionResult ToImpressionResult(ImpressionResult result) { + switch (result) { + case ImpressionResult::kInvalid: + return proto::Impression_ImpressionResult_INVALID; + case ImpressionResult::kPositive: + return proto::Impression_ImpressionResult_POSITIVE; + case ImpressionResult::kNegative: + return proto::Impression_ImpressionResult_NEGATIVE; + case ImpressionResult::kNeutral: + return proto::Impression_ImpressionResult_NEUTRAL; + } + NOTREACHED(); +} + +// Converts ImpressionResult from its associated enum in proto buffer. +ImpressionResult FromImpressionResult( + proto::Impression_ImpressionResult result) { + switch (result) { + case proto::Impression_ImpressionResult_INVALID: + return ImpressionResult::kInvalid; + case proto::Impression_ImpressionResult_POSITIVE: + return ImpressionResult::kPositive; + case proto::Impression_ImpressionResult_NEGATIVE: + return ImpressionResult::kNegative; + case proto::Impression_ImpressionResult_NEUTRAL: + return ImpressionResult::kNeutral; + } + NOTREACHED(); +} + +// Converts ImpressionResult to its associated enum in proto buffer. +proto::Impression_SchedulerTaskTime ToSchedulerTaskTime( + SchedulerTaskTime time) { + switch (time) { + case SchedulerTaskTime::kUnknown: + return proto::Impression_SchedulerTaskTime_UNKNOWN_TASK_TIME; + case SchedulerTaskTime::kMorning: + return proto::Impression_SchedulerTaskTime_MORNING; + case SchedulerTaskTime::kEvening: + return proto::Impression_SchedulerTaskTime_EVENING; + } + NOTREACHED(); +} + +// Converts ImpressionResult from its associated enum in proto buffer. +SchedulerTaskTime FromSchedulerTaskTime( + proto::Impression_SchedulerTaskTime time) { + switch (time) { + case proto::Impression_SchedulerTaskTime_UNKNOWN_TASK_TIME: + return SchedulerTaskTime::kUnknown; + case proto::Impression_SchedulerTaskTime_MORNING: + return SchedulerTaskTime::kMorning; + case proto::Impression_SchedulerTaskTime_EVENING: + return SchedulerTaskTime::kEvening; + } + NOTREACHED(); +} + +} // namespace + void IconEntryToProto(IconEntry* entry, notifications::proto::Icon* proto) { proto->mutable_uuid()->swap(entry->uuid); proto->mutable_icon()->swap(entry->data); } -void IconProtoToEntry(proto::Icon* proto, notifications::IconEntry* entry) { +void IconEntryFromProto(proto::Icon* proto, notifications::IconEntry* entry) { DCHECK(proto->has_uuid()); DCHECK(proto->has_icon()); entry->data.swap(*proto->mutable_icon()); entry->uuid.swap(*proto->mutable_uuid()); } +void ClientStateToProto(ClientState* client_state, + notifications::proto::ClientState* proto) { + proto->set_type(ToSchedulerClientType(client_state->type)); + proto->set_current_max_daily_show(client_state->current_max_daily_show); + + for (const auto& impression : client_state->impressions) { + auto* impression_ptr = proto->add_impressions(); + impression_ptr->set_create_time(TimeToMilliseconds(impression.create_time)); + impression_ptr->set_feedback(ToUserFeedback(impression.feedback)); + impression_ptr->set_impression(ToImpressionResult(impression.impression)); + impression_ptr->set_integrated(impression.integrated); + impression_ptr->set_task_start_time( + ToSchedulerTaskTime(impression.task_start_time)); + } + + if (client_state->suppression_info.has_value()) { + const auto& suppression = *client_state->suppression_info; + auto* suppression_proto = proto->mutable_suppression_info(); + suppression_proto->set_last_trigger_time( + TimeToMilliseconds(suppression.last_trigger_time)); + suppression_proto->set_duration_ms( + TimeDeltaToMilliseconds(suppression.duration)); + suppression_proto->set_recover_goal(suppression.recover_goal); + } +} + +void ClientStateFromProto(proto::ClientState* proto, + notifications::ClientState* client_state) { + DCHECK(proto->has_type()); + DCHECK(proto->has_current_max_daily_show()); + client_state->type = FromSchedulerClientType(proto->type()); + client_state->current_max_daily_show = proto->current_max_daily_show(); + + for (const auto& proto_impression : proto->impressions()) { + Impression impression; + DCHECK(proto_impression.has_create_time()); + impression.create_time = MillisecondsToTime(proto_impression.create_time()); + impression.feedback = FromUserFeedback(proto_impression.feedback()); + impression.impression = FromImpressionResult(proto_impression.impression()); + impression.integrated = proto_impression.integrated(); + impression.task_start_time = + FromSchedulerTaskTime(proto_impression.task_start_time()); + client_state->impressions.emplace_back(std::move(impression)); + } + + if (proto->has_suppression_info()) { + const auto& proto_suppression = proto->suppression_info(); + DCHECK(proto_suppression.has_last_trigger_time()); + DCHECK(proto_suppression.has_duration_ms()); + DCHECK(proto_suppression.has_recover_goal()); + + SuppressionInfo suppression_info( + MillisecondsToTime(proto_suppression.last_trigger_time()), + MillisecondsToTimeDelta(proto_suppression.duration_ms())); + suppression_info.recover_goal = proto_suppression.recover_goal(); + client_state->suppression_info = std::move(suppression_info); + } +} + } // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/proto_conversion.h b/chrome/browser/notifications/scheduler/proto_conversion.h index eee7422..5795db2 100644 --- a/chrome/browser/notifications/scheduler/proto_conversion.h +++ b/chrome/browser/notifications/scheduler/proto_conversion.h
@@ -8,8 +8,10 @@ #include <memory> #include "base/macros.h" +#include "chrome/browser/notifications/proto/client_state.pb.h" #include "chrome/browser/notifications/proto/icon.pb.h" #include "chrome/browser/notifications/scheduler/icon_entry.h" +#include "chrome/browser/notifications/scheduler/impression_types.h" namespace notifications { @@ -17,7 +19,15 @@ void IconEntryToProto(IconEntry* entry, notifications::proto::Icon* proto); // Converts an icon proto to icon entry. -void IconProtoToEntry(proto::Icon* proto, notifications::IconEntry* entry); +void IconEntryFromProto(proto::Icon* proto, notifications::IconEntry* entry); + +// Converts client state to proto. +void ClientStateToProto(ClientState* client_state, + notifications::proto::ClientState* proto); + +// Converts proto to client state. +void ClientStateFromProto(proto::ClientState* proto, + notifications::ClientState* client_state); } // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/proto_conversion_unittest.cc b/chrome/browser/notifications/scheduler/proto_conversion_unittest.cc index ba37e9ad..0430ca0 100644 --- a/chrome/browser/notifications/scheduler/proto_conversion_unittest.cc +++ b/chrome/browser/notifications/scheduler/proto_conversion_unittest.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/notifications/scheduler/proto_conversion.h" #include "base/logging.h" +#include "chrome/browser/notifications/scheduler/test/test_utils.h" #include "testing/gtest/include/gtest/gtest.h" using IconProto = notifications::proto::Icon; @@ -15,13 +16,24 @@ const char kUuid[] = "123"; const char kData[] = "bitmapdata"; -TEST(ProtoConversionTest, IconProtoToEntry) { +void TestClientStateConversion(ClientState* client_state) { + DCHECK(client_state); + notifications::proto::ClientState proto; + ClientState expected; + ClientStateToProto(client_state, &proto); + ClientStateFromProto(&proto, &expected); + EXPECT_EQ(*client_state, expected) + << " \n Output: \n " << client_state->DebugPrint() << " \n Expected: \n" + << expected.DebugPrint(); +} + +TEST(ProtoConversionTest, IconEntryFromProto) { IconProto proto; proto.set_uuid(kUuid); proto.set_icon(kData); IconEntry entry; - IconProtoToEntry(&proto, &entry); + IconEntryFromProto(&proto, &entry); // Verify entry data. EXPECT_EQ(entry.uuid, kUuid); @@ -41,5 +53,87 @@ EXPECT_EQ(proto.uuid(), kUuid); } +// Verifies client state proto conversion. +TEST(ProtoConversionTest, ClientStateProtoConversion) { + // Verify basic fields. + ClientState client_state; + test::ImpressionTestData test_data{ + SchedulerClientType::kTest1, 3, {}, base::nullopt}; + test::AddImpressionTestData(test_data, &client_state); + TestClientStateConversion(&client_state); + + // Verify suppression info. + base::Time last_trigger_time; + bool success = + base::Time::FromString("04/25/20 01:00:00 AM", &last_trigger_time); + DCHECK(success); + auto duration = base::TimeDelta::FromDays(7); + auto suppression = SuppressionInfo(last_trigger_time, duration); + suppression.recover_goal = 5; + client_state.suppression_info = std::move(suppression); + TestClientStateConversion(&client_state); +} + +// Verifies impression proto conversion. +TEST(ProtoConversionTest, ImpressionProtoConversion) { + ClientState client_state; + base::Time create_time; + bool success = base::Time::FromString("03/25/19 00:00:00 AM", &create_time); + DCHECK(success); + Impression impression{create_time, UserFeedback::kHelpful, + ImpressionResult::kPositive, true, + SchedulerTaskTime::kMorning}; + client_state.impressions.emplace_back(impression); + TestClientStateConversion(&client_state); + + auto& first_impression = *client_state.impressions.begin(); + + // Verify all feedback types. + std::vector<UserFeedback> feedback_types{ + UserFeedback::kNoFeedback, UserFeedback::kHelpful, + UserFeedback::kNotHelpful, UserFeedback::kClick, + UserFeedback::kDismiss, UserFeedback::kIgnore}; + for (const auto feedback_type : feedback_types) { + first_impression.feedback = feedback_type; + TestClientStateConversion(&client_state); + } + + // Verify all impression result types. + std::vector<ImpressionResult> impression_results{ + ImpressionResult::kInvalid, ImpressionResult::kPositive, + ImpressionResult::kNegative, ImpressionResult::kNeutral}; + for (const auto impression_result : impression_results) { + first_impression.impression = impression_result; + TestClientStateConversion(&client_state); + } + + // Verify all scheduler task time types. + std::vector<SchedulerTaskTime> task_times{SchedulerTaskTime::kUnknown, + SchedulerTaskTime::kMorning, + SchedulerTaskTime::kEvening}; + for (const auto task_start_time : task_times) { + first_impression.task_start_time = task_start_time; + TestClientStateConversion(&client_state); + } +} + +// Verifies multiple impressions are serialized correctly. +TEST(ProtoConversionTest, MultipleImpressionConversion) { + ClientState client_state; + base::Time create_time; + bool success = base::Time::FromString("04/25/20 01:00:00 AM", &create_time); + DCHECK(success); + + Impression impression{create_time, UserFeedback::kHelpful, + ImpressionResult::kPositive, true, + SchedulerTaskTime::kMorning}; + Impression other_impression{create_time, UserFeedback::kNoFeedback, + ImpressionResult::kNegative, false, + SchedulerTaskTime::kEvening}; + client_state.impressions.emplace_back(std::move(impression)); + client_state.impressions.emplace_back(std::move(other_impression)); + TestClientStateConversion(&client_state); +} + } // namespace } // namespace notifications
diff --git a/chrome/browser/notifications/scheduler/test/test_utils.cc b/chrome/browser/notifications/scheduler/test/test_utils.cc index 38f17cd..b7cb20ae 100644 --- a/chrome/browser/notifications/scheduler/test/test_utils.cc +++ b/chrome/browser/notifications/scheduler/test/test_utils.cc
@@ -22,17 +22,24 @@ ImpressionTestData::~ImpressionTestData() = default; +void AddImpressionTestData(const ImpressionTestData& data, + ClientState* client_state) { + DCHECK(client_state); + client_state->type = data.type; + client_state->current_max_daily_show = data.current_max_daily_show; + for (const auto& impression : data.impressions) { + client_state->impressions.emplace_back(impression); + } + client_state->suppression_info = data.suppression_info; +} + void AddImpressionTestData( const std::vector<ImpressionTestData>& test_data, ImpressionHistoryTracker::ClientStates* client_states) { DCHECK(client_states); for (const auto& test_data : test_data) { - auto client_state = std::make_unique<ClientState>(test_data.type); - client_state->current_max_daily_show = test_data.current_max_daily_show; - for (const auto& impression : test_data.impressions) { - client_state->impressions.emplace_back(impression); - } - client_state->suppression_info = test_data.suppression_info; + auto client_state = std::make_unique<ClientState>(); + AddImpressionTestData(test_data, client_state.get()); client_states->emplace(test_data.type, std::move(client_state)); } }
diff --git a/chrome/browser/notifications/scheduler/test/test_utils.h b/chrome/browser/notifications/scheduler/test/test_utils.h index 32f218c..bea9a70 100644 --- a/chrome/browser/notifications/scheduler/test/test_utils.h +++ b/chrome/browser/notifications/scheduler/test/test_utils.h
@@ -28,6 +28,10 @@ base::Optional<SuppressionInfo> suppression_info; }; +// Add one impression test data into a client state. +void AddImpressionTestData(const ImpressionTestData& data, + ClientState* client_state); + // Adds impression test data into client states container. void AddImpressionTestData( const std::vector<ImpressionTestData>& test_data,
diff --git a/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc b/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc index a452293..519d355 100644 --- a/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc +++ b/chrome/browser/performance_manager/chrome_content_browser_client_performance_manager_part.cc
@@ -51,11 +51,9 @@ base::Unretained(render_process_host)), base::SequencedTaskRunnerHandle::Get()); - // When a RenderFrameHost is "resurrected" with a new process it will already - // have user data attached. This will happen on renderer crash. - if (!performance_manager::RenderProcessUserData::GetForRenderProcessHost( - render_process_host)) { - performance_manager::RenderProcessUserData::CreateForRenderProcessHost( - render_process_host); - } + // Ideally this would strictly be a "CreateForRenderProcess", but when a + // RenderFrameHost is "resurrected" with a new process it will already have + // user data attached. This will happen on renderer crash. + performance_manager::RenderProcessUserData::GetOrCreateForRenderProcessHost( + render_process_host); }
diff --git a/chrome/browser/performance_manager/graph/frame_node_impl.cc b/chrome/browser/performance_manager/graph/frame_node_impl.cc index 08c6eed3..daa0c0f 100644 --- a/chrome/browser/performance_manager/graph/frame_node_impl.cc +++ b/chrome/browser/performance_manager/graph/frame_node_impl.cc
@@ -12,13 +12,18 @@ namespace performance_manager { FrameNodeImpl::FrameNodeImpl(Graph* graph, + ProcessNodeImpl* process_node, PageNodeImpl* page_node, - FrameNodeImpl* parent_frame_node) + FrameNodeImpl* parent_frame_node, + int frame_tree_node_id) : CoordinationUnitInterface(graph), parent_frame_node_(parent_frame_node), page_node_(page_node), - process_node_(nullptr) { + process_node_(process_node), + frame_tree_node_id_(frame_tree_node_id) { DETACH_FROM_SEQUENCE(sequence_checker_); + DCHECK(process_node); + DCHECK(page_node); } FrameNodeImpl::~FrameNodeImpl() { @@ -39,10 +44,8 @@ lifecycle_state_ = state; // Notify parents of this change. - if (process_node_) - process_node_->OnFrameLifecycleStateChanged(this, old_state); - if (page_node_) - page_node_->OnFrameLifecycleStateChanged(this, old_state); + process_node_->OnFrameLifecycleStateChanged(this, old_state); + page_node_->OnFrameLifecycleStateChanged(this, old_state); } void FrameNodeImpl::SetHasNonEmptyBeforeUnload(bool has_nonempty_beforeunload) { @@ -91,10 +94,13 @@ } ProcessNodeImpl* FrameNodeImpl::process_node() const { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return process_node_; } +int FrameNodeImpl::frame_tree_node_id() const { + return frame_tree_node_id_; +} + const std::set<FrameNodeImpl*>& FrameNodeImpl::child_frame_nodes() const { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); return child_frame_nodes_; @@ -121,14 +127,6 @@ return network_almost_idle_.value(); } -void FrameNodeImpl::SetProcess(ProcessNodeImpl* process_node) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(NodeInGraph(process_node)); - DCHECK(!process_node_); - process_node_ = process_node; - process_node->AddFrame(this); -} - void FrameNodeImpl::set_url(const GURL& url) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); url_ = url; @@ -205,13 +203,11 @@ intervention_policy_[i] = resource_coordinator::mojom::InterventionPolicy::kUnknown; - // Hook up the frame hierarchy. + // Wire this up to the other nodes in the graph. if (parent_frame_node_) parent_frame_node_->AddChildFrame(this); - - // And join the page. - // TODO(siggi): Only do this for the main frame and retire the frame set. page_node_->AddFrame(this); + process_node_->AddFrame(this); NodeBase::JoinGraph(); } @@ -232,10 +228,9 @@ parent_frame_node_->RemoveChildFrame(this); } - if (process_node_) { - DCHECK(NodeInGraph(process_node_)); - process_node_->RemoveFrame(this); - } + // And leave the process. + DCHECK(NodeInGraph(process_node_)); + process_node_->RemoveFrame(this); } void FrameNodeImpl::OnEventReceived(resource_coordinator::mojom::Event event) { @@ -264,10 +259,4 @@ return false; } -void FrameNodeImpl::RemoveProcessNode(ProcessNodeImpl* process_node) { - DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(process_node == process_node_); - process_node_ = nullptr; -} - } // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/frame_node_impl.h b/chrome/browser/performance_manager/graph/frame_node_impl.h index a33e55b9..274ab4f 100644 --- a/chrome/browser/performance_manager/graph/frame_node_impl.h +++ b/chrome/browser/performance_manager/graph/frame_node_impl.h
@@ -31,12 +31,14 @@ return resource_coordinator::CoordinationUnitType::kFrame; } - // Construct a frame node associated with |page_node| and optionally with a - // |parent_frame_node|. For the main frame of |page_node| the - // |parent_frame_node| parameter should be nullptr. + // Construct a frame node associated with a |process_node|, a |page_node| and + // optionally with a |parent_frame_node|. For the main frame of |page_node| + // the |parent_frame_node| parameter should be nullptr. FrameNodeImpl(Graph* graph, + ProcessNodeImpl* process_node, PageNodeImpl* page_node, - FrameNodeImpl* parent_frame_node); + FrameNodeImpl* parent_frame_node, + int frame_tree_node_id); ~FrameNodeImpl() override; // FrameNode implementation. @@ -52,18 +54,17 @@ // Getters for const properties. These can be called from any thread. FrameNodeImpl* parent_frame_node() const; PageNodeImpl* page_node() const; + ProcessNodeImpl* process_node() const; + int frame_tree_node_id() const; // Getters for non-const properties. These are not thread safe. - ProcessNodeImpl* process_node() const; const std::set<FrameNodeImpl*>& child_frame_nodes() const; resource_coordinator::mojom::LifecycleState lifecycle_state() const; bool has_nonempty_beforeunload() const; const GURL& url() const; bool network_almost_idle() const; - // Setters can only be called from the performance manager sequence. - // TODO(siggi): The process node can be provided at construction. - void SetProcess(ProcessNodeImpl* process_node); + // Setters are not thread safe. void set_url(const GURL& url); // A frame is a main frame if it has no |parent_frame_node|. This can be @@ -95,12 +96,13 @@ bool HasFrameNodeInAncestors(FrameNodeImpl* frame_node) const; bool HasFrameNodeInDescendants(FrameNodeImpl* frame_node) const; - void RemoveProcessNode(ProcessNodeImpl* process_node); - FrameNodeImpl* const parent_frame_node_; PageNodeImpl* const page_node_; + ProcessNodeImpl* const process_node_; + // Can be used to tie together "sibling" frames, where a navigation is ongoing + // in a new frame that will soon replace the existing one. + const int frame_tree_node_id_; - ProcessNodeImpl* process_node_; std::set<FrameNodeImpl*> child_frame_nodes_; resource_coordinator::mojom::LifecycleState lifecycle_state_ = resource_coordinator::mojom::LifecycleState::kRunning;
diff --git a/chrome/browser/performance_manager/graph/frame_node_impl_unittest.cc b/chrome/browser/performance_manager/graph/frame_node_impl_unittest.cc index bda0fc1d..700c4eb2 100644 --- a/chrome/browser/performance_manager/graph/frame_node_impl_unittest.cc +++ b/chrome/browser/performance_manager/graph/frame_node_impl_unittest.cc
@@ -37,10 +37,14 @@ } // namespace TEST_F(FrameNodeImplTest, AddFrameHierarchyBasic) { + auto process = CreateNode<ProcessNodeImpl>(); auto page = CreateNode<PageNodeImpl>(); - auto parent_node = CreateNode<FrameNodeImpl>(page.get(), nullptr); - auto child2_node = CreateNode<FrameNodeImpl>(page.get(), parent_node.get()); - auto child3_node = CreateNode<FrameNodeImpl>(page.get(), parent_node.get()); + auto parent_node = + CreateNode<FrameNodeImpl>(process.get(), page.get(), nullptr, 0); + auto child2_node = CreateNode<FrameNodeImpl>(process.get(), page.get(), + parent_node.get(), 1); + auto child3_node = CreateNode<FrameNodeImpl>(process.get(), page.get(), + parent_node.get(), 2); EXPECT_EQ(nullptr, parent_node->parent_frame_node()); EXPECT_EQ(2u, parent_node->child_frame_nodes().size()); @@ -49,8 +53,10 @@ } TEST_F(FrameNodeImplTest, Url) { + auto process = CreateNode<ProcessNodeImpl>(); auto page = CreateNode<PageNodeImpl>(); - auto frame_node = CreateNode<FrameNodeImpl>(page.get(), nullptr); + auto frame_node = + CreateNode<FrameNodeImpl>(process.get(), page.get(), nullptr, 0); EXPECT_TRUE(frame_node->url().is_empty()); const GURL url("http://www.foo.com/"); frame_node->set_url(url); @@ -58,10 +64,12 @@ } TEST_F(FrameNodeImplTest, RemoveChildFrame) { + auto process = CreateNode<ProcessNodeImpl>(); auto page = CreateNode<PageNodeImpl>(); - auto parent_frame_node = CreateNode<FrameNodeImpl>(page.get(), nullptr); - auto child_frame_node = - CreateNode<FrameNodeImpl>(page.get(), parent_frame_node.get()); + auto parent_frame_node = + CreateNode<FrameNodeImpl>(process.get(), page.get(), nullptr, 0); + auto child_frame_node = CreateNode<FrameNodeImpl>(process.get(), page.get(), + parent_frame_node.get(), 1); // Ensure correct Parent-child relationships have been established. EXPECT_EQ(1u, parent_frame_node->child_frame_nodes().size());
diff --git a/chrome/browser/performance_manager/graph/mock_graphs.cc b/chrome/browser/performance_manager/graph/mock_graphs.cc index 72260e41..ff36ddf 100644 --- a/chrome/browser/performance_manager/graph/mock_graphs.cc +++ b/chrome/browser/performance_manager/graph/mock_graphs.cc
@@ -21,11 +21,13 @@ : system(TestNodeWrapper<SystemNodeImpl>::Create(graph)), process(TestNodeWrapper<ProcessNodeImpl>::Create(graph)), page(TestNodeWrapper<PageNodeImpl>::Create(graph)), - frame( - TestNodeWrapper<FrameNodeImpl>::Create(graph, page.get(), nullptr)) { + frame(TestNodeWrapper<FrameNodeImpl>::Create(graph, + process.get(), + page.get(), + nullptr, + 0)) { frame->SetAllInterventionPoliciesForTesting( resource_coordinator::mojom::InterventionPolicy::kDefault); - frame->SetProcess(process.get()); process->SetPID(1); } @@ -40,11 +42,12 @@ : MockSinglePageInSingleProcessGraph(graph), other_page(TestNodeWrapper<PageNodeImpl>::Create(graph)), other_frame(TestNodeWrapper<FrameNodeImpl>::Create(graph, + process.get(), other_page.get(), - nullptr)) { + nullptr, + 1)) { other_frame->SetAllInterventionPoliciesForTesting( resource_coordinator::mojom::InterventionPolicy::kDefault); - other_frame->SetProcess(process.get()); } MockMultiplePagesInSingleProcessGraph:: @@ -56,14 +59,15 @@ MockSinglePageWithMultipleProcessesGraph:: MockSinglePageWithMultipleProcessesGraph(Graph* graph) : MockSinglePageInSingleProcessGraph(graph), + other_process(TestNodeWrapper<ProcessNodeImpl>::Create(graph)), child_frame(TestNodeWrapper<FrameNodeImpl>::Create(graph, + other_process.get(), page.get(), - frame.get())), - other_process(TestNodeWrapper<ProcessNodeImpl>::Create(graph)) { + frame.get(), + 2)) { + other_process->SetPID(2); child_frame->SetAllInterventionPoliciesForTesting( resource_coordinator::mojom::InterventionPolicy::kDefault); - child_frame->SetProcess(other_process.get()); - other_process->SetPID(2); } MockSinglePageWithMultipleProcessesGraph:: @@ -72,14 +76,15 @@ MockMultiplePagesWithMultipleProcessesGraph:: MockMultiplePagesWithMultipleProcessesGraph(Graph* graph) : MockMultiplePagesInSingleProcessGraph(graph), + other_process(TestNodeWrapper<ProcessNodeImpl>::Create(graph)), child_frame(TestNodeWrapper<FrameNodeImpl>::Create(graph, + other_process.get(), other_page.get(), - other_frame.get())), - other_process(TestNodeWrapper<ProcessNodeImpl>::Create(graph)) { + other_frame.get(), + 3)) { + other_process->SetPID(2); child_frame->SetAllInterventionPoliciesForTesting( resource_coordinator::mojom::InterventionPolicy::kDefault); - child_frame->SetProcess(other_process.get()); - other_process->SetPID(2); } MockMultiplePagesWithMultipleProcessesGraph::
diff --git a/chrome/browser/performance_manager/graph/mock_graphs.h b/chrome/browser/performance_manager/graph/mock_graphs.h index 9937128..d0aeb99 100644 --- a/chrome/browser/performance_manager/graph/mock_graphs.h +++ b/chrome/browser/performance_manager/graph/mock_graphs.h
@@ -23,7 +23,7 @@ // F // // Where: -// F: frame +// F: frame(frame_tree_id:0) // Pr: process(pid:1) // Pg: page struct MockSinglePageInSingleProcessGraph { @@ -43,8 +43,8 @@ // F OF // // Where: -// F: frame -// OF: other_frame +// F: frame(frame_tree_id:0) +// OF: other_frame(frame_tree_id:1) // Pg: page // OPg: other_page // Pr: process(pid:1) @@ -67,8 +67,8 @@ // |__CF // // Where: -// F: frame -// CF: child_frame +// F: frame(frame_tree_id:0) +// CF: child_frame(frame_tree_id:2) // Pg: page // Pr: process(pid:1) // OPr: other_process(pid:2) @@ -76,8 +76,8 @@ : public MockSinglePageInSingleProcessGraph { explicit MockSinglePageWithMultipleProcessesGraph(Graph* graph); ~MockSinglePageWithMultipleProcessesGraph(); - TestNodeWrapper<FrameNodeImpl> child_frame; TestNodeWrapper<ProcessNodeImpl> other_process; + TestNodeWrapper<FrameNodeImpl> child_frame; }; // The following coordination unit graph topology is created to emulate a @@ -91,9 +91,9 @@ // CF___| // // Where: -// F: frame -// OF: other_frame -// CF: another_frame +// F: frame(frame_tree_id:0) +// OF: other_frame(frame_tree_id:1) +// CF: child_frame(frame_tree_id:3) // Pg: page // OPg: other_page // Pr: process(pid:1) @@ -102,8 +102,8 @@ : public MockMultiplePagesInSingleProcessGraph { explicit MockMultiplePagesWithMultipleProcessesGraph(Graph* graph); ~MockMultiplePagesWithMultipleProcessesGraph(); - TestNodeWrapper<FrameNodeImpl> child_frame; TestNodeWrapper<ProcessNodeImpl> other_process; + TestNodeWrapper<FrameNodeImpl> child_frame; }; } // namespace performance_manager
diff --git a/chrome/browser/performance_manager/graph/page_node_impl_unittest.cc b/chrome/browser/performance_manager/graph/page_node_impl_unittest.cc index 57c3e3d..2c6250c 100644 --- a/chrome/browser/performance_manager/graph/page_node_impl_unittest.cc +++ b/chrome/browser/performance_manager/graph/page_node_impl_unittest.cc
@@ -39,20 +39,24 @@ } // namespace TEST_F(PageNodeImplTest, AddFrameBasic) { + auto process_node = CreateNode<ProcessNodeImpl>(); auto page_node = CreateNode<PageNodeImpl>(); - auto parent_frame = CreateNode<FrameNodeImpl>(page_node.get(), nullptr); - auto child1_frame = - CreateNode<FrameNodeImpl>(page_node.get(), parent_frame.get()); - auto child2_frame = - CreateNode<FrameNodeImpl>(page_node.get(), parent_frame.get()); + auto parent_frame = CreateNode<FrameNodeImpl>(process_node.get(), + page_node.get(), nullptr, 0); + auto child1_frame = CreateNode<FrameNodeImpl>( + process_node.get(), page_node.get(), parent_frame.get(), 1); + auto child2_frame = CreateNode<FrameNodeImpl>( + process_node.get(), page_node.get(), parent_frame.get(), 2); // Validate that all frames are tallied to the page. EXPECT_EQ(3u, page_node->GetFrameNodes().size()); } TEST_F(PageNodeImplTest, RemoveFrame) { + auto process_node = CreateNode<ProcessNodeImpl>(); auto page_node = CreateNode<PageNodeImpl>(); - auto frame_node = CreateNode<FrameNodeImpl>(page_node.get(), nullptr); + auto frame_node = CreateNode<FrameNodeImpl>(process_node.get(), + page_node.get(), nullptr, 0); // Ensure correct page-frame relationship has been established. EXPECT_EQ(1u, page_node->GetFrameNodes().size()); @@ -220,7 +224,8 @@ resource_coordinator::mojom::InterventionPolicy f1_policy, resource_coordinator::mojom::InterventionPolicy f0_policy_aggregated, resource_coordinator::mojom::InterventionPolicy f0f1_policy_aggregated) { - + TestNodeWrapper<ProcessNodeImpl> process = + TestNodeWrapper<ProcessNodeImpl>::Create(mock_graph); TestNodeWrapper<PageNodeImpl> page = TestNodeWrapper<PageNodeImpl>::Create(mock_graph); @@ -232,8 +237,8 @@ resource_coordinator::mojom::InterventionPolicy::kUnknown, page.get()); // Create an initial frame. - TestNodeWrapper<FrameNodeImpl> f0 = - TestNodeWrapper<FrameNodeImpl>::Create(mock_graph, page.get(), nullptr); + TestNodeWrapper<FrameNodeImpl> f0 = TestNodeWrapper<FrameNodeImpl>::Create( + mock_graph, process.get(), page.get(), nullptr, 0); // Add a frame and expect the values to be invalidated. Reaggregate and // ensure the appropriate value results. f0->SetAllInterventionPoliciesForTesting(f0_policy); @@ -242,8 +247,8 @@ resource_coordinator::mojom::InterventionPolicy::kUnknown, page.get()); ExpectInterventionPolicy(f0_policy_aggregated, page.get()); - TestNodeWrapper<FrameNodeImpl> f1 = - TestNodeWrapper<FrameNodeImpl>::Create(mock_graph, page.get(), f0.get()); + TestNodeWrapper<FrameNodeImpl> f1 = TestNodeWrapper<FrameNodeImpl>::Create( + mock_graph, process.get(), page.get(), f0.get(), 1); // Do it again. This time the raw values should be the same as the // aggregated values above. f1->SetAllInterventionPoliciesForTesting(f1_policy); @@ -360,14 +365,16 @@ TEST_F(PageNodeImplTest, IncrementalInterventionPolicy) { auto* mock_graph = graph(); + TestNodeWrapper<ProcessNodeImpl> process = + TestNodeWrapper<ProcessNodeImpl>::Create(mock_graph); TestNodeWrapper<PageNodeImpl> page = TestNodeWrapper<PageNodeImpl>::Create(mock_graph); // Create two frames and immediately attach them to the page. - TestNodeWrapper<FrameNodeImpl> f0 = - TestNodeWrapper<FrameNodeImpl>::Create(mock_graph, page.get(), nullptr); - TestNodeWrapper<FrameNodeImpl> f1 = - TestNodeWrapper<FrameNodeImpl>::Create(mock_graph, page.get(), f0.get()); + TestNodeWrapper<FrameNodeImpl> f0 = TestNodeWrapper<FrameNodeImpl>::Create( + mock_graph, process.get(), page.get(), nullptr, 0); + TestNodeWrapper<FrameNodeImpl> f1 = TestNodeWrapper<FrameNodeImpl>::Create( + mock_graph, process.get(), page.get(), f0.get(), 1); EXPECT_EQ(0u, page->GetInterventionPolicyFramesReportedForTesting()); EXPECT_EQ(0u, page->GetInterventionPolicyFramesReportedForTesting()); EXPECT_EQ(0u, page->GetInterventionPolicyFramesReportedForTesting());
diff --git a/chrome/browser/performance_manager/graph/process_node_impl.cc b/chrome/browser/performance_manager/graph/process_node_impl.cc index 0aeb6ea..b5264e5 100644 --- a/chrome/browser/performance_manager/graph/process_node_impl.cc +++ b/chrome/browser/performance_manager/graph/process_node_impl.cc
@@ -122,8 +122,8 @@ if (process_id_ != base::kNullProcessId) graph()->BeforeProcessPidChange(this, base::kNullProcessId); - for (auto* child_frame : frame_nodes_) - child_frame->RemoveProcessNode(this); + // All child frames should have been removed before the process is removed. + DCHECK(frame_nodes_.empty()); } void ProcessNodeImpl::OnEventReceived(
diff --git a/chrome/browser/performance_manager/observers/graph_observer_unittest.cc b/chrome/browser/performance_manager/observers/graph_observer_unittest.cc index d0d8c77..12187ca 100644 --- a/chrome/browser/performance_manager/observers/graph_observer_unittest.cc +++ b/chrome/browser/performance_manager/observers/graph_observer_unittest.cc
@@ -52,11 +52,12 @@ { - auto page_node = CreateNode<PageNodeImpl>(); auto process_node = CreateNode<ProcessNodeImpl>(); - auto root_frame_node = CreateNode<FrameNodeImpl>(page_node.get(), nullptr); - auto frame_node = - CreateNode<FrameNodeImpl>(page_node.get(), root_frame_node.get()); + auto page_node = CreateNode<PageNodeImpl>(); + auto root_frame_node = CreateNode<FrameNodeImpl>( + process_node.get(), page_node.get(), nullptr, 0); + auto frame_node = CreateNode<FrameNodeImpl>( + process_node.get(), page_node.get(), root_frame_node.get(), 1); EXPECT_EQ(2u, observer->node_created_count()); }
diff --git a/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc b/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc index 05072c16..403496e 100644 --- a/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc +++ b/chrome/browser/performance_manager/observers/metrics_collector_unittest.cc
@@ -113,8 +113,10 @@ TEST_F(MAYBE_MetricsCollectorTest, FromBackgroundedToFirstNonPersistentNotificationCreatedUMA) { + auto process_node = CreateNode<ProcessNodeImpl>(); auto page_node = CreateNode<PageNodeImpl>(); - auto frame_node = CreateNode<FrameNodeImpl>(page_node.get(), nullptr); + auto frame_node = CreateNode<FrameNodeImpl>(process_node.get(), + page_node.get(), nullptr, 0); page_node->OnMainFrameNavigationCommitted(PerformanceManagerClock::NowTicks(), kDummyID, kDummyUrl); @@ -148,8 +150,10 @@ TEST_F( MAYBE_MetricsCollectorTest, FromBackgroundedToFirstNonPersistentNotificationCreatedUMA5MinutesTimeout) { + auto process_node = CreateNode<ProcessNodeImpl>(); auto page_node = CreateNode<PageNodeImpl>(); - auto frame_node = CreateNode<FrameNodeImpl>(page_node.get(), nullptr); + auto frame_node = CreateNode<FrameNodeImpl>(process_node.get(), + page_node.get(), nullptr, 0); page_node->OnMainFrameNavigationCommitted(PerformanceManagerClock::NowTicks(), kDummyID, kDummyUrl); @@ -217,11 +221,10 @@ // Flaky test: https://crbug.com/833028 TEST_F(MAYBE_MetricsCollectorTest, ResponsivenessMetric) { - auto page_node = CreateNode<PageNodeImpl>(); auto process_node = CreateNode<ProcessNodeImpl>(); - - auto frame_node = CreateNode<FrameNodeImpl>(page_node.get(), nullptr); - frame_node->SetProcess(process_node.get()); + auto page_node = CreateNode<PageNodeImpl>(); + auto frame_node = CreateNode<FrameNodeImpl>(process_node.get(), + page_node.get(), nullptr, 0); ukm::TestUkmRecorder ukm_recorder; graph()->set_ukm_recorder(&ukm_recorder);
diff --git a/chrome/browser/performance_manager/performance_manager.cc b/chrome/browser/performance_manager/performance_manager.cc index dae724cc..57a6713 100644 --- a/chrome/browser/performance_manager/performance_manager.cc +++ b/chrome/browser/performance_manager/performance_manager.cc
@@ -7,6 +7,7 @@ #include <memory> #include <utility> +#include "base/containers/flat_set.h" #include "base/feature_list.h" #include "base/logging.h" #include "base/macros.h" @@ -81,23 +82,34 @@ } std::unique_ptr<FrameNodeImpl> PerformanceManager::CreateFrameNode( + ProcessNodeImpl* process_node, PageNodeImpl* page_node, - FrameNodeImpl* parent_frame_node) { - std::unique_ptr<FrameNodeImpl> new_node = - std::make_unique<FrameNodeImpl>(&graph_, page_node, parent_frame_node); - task_runner_->PostTask( - FROM_HERE, base::BindOnce(&Graph::AddNewNode, base::Unretained(&graph_), - base::Unretained(new_node.get()))); + FrameNodeImpl* parent_frame_node, + int frame_tree_node_id) { + return CreateNodeImpl<FrameNodeImpl>(FrameNodeCreationCallback(), + process_node, page_node, + parent_frame_node, frame_tree_node_id); +} - return new_node; +std::unique_ptr<FrameNodeImpl> PerformanceManager::CreateFrameNode( + ProcessNodeImpl* process_node, + PageNodeImpl* page_node, + FrameNodeImpl* parent_frame_node, + int frame_tree_node_id, + FrameNodeCreationCallback creation_callback) { + return CreateNodeImpl<FrameNodeImpl>(std::move(creation_callback), + process_node, page_node, + parent_frame_node, frame_tree_node_id); } std::unique_ptr<PageNodeImpl> PerformanceManager::CreatePageNode() { - return CreateNodeImpl<PageNodeImpl>(); + return CreateNodeImpl<PageNodeImpl>( + base::OnceCallback<void(PageNodeImpl*)>()); } std::unique_ptr<ProcessNodeImpl> PerformanceManager::CreateProcessNode() { - return CreateNodeImpl<ProcessNodeImpl>(); + return CreateNodeImpl<ProcessNodeImpl>( + base::OnceCallback<void(ProcessNodeImpl*)>()); } void PerformanceManager::BatchDeleteNodes( @@ -122,13 +134,33 @@ std::move(message_pipe))); } -template <typename NodeType> -std::unique_ptr<NodeType> PerformanceManager::CreateNodeImpl() { - std::unique_ptr<NodeType> new_node = std::make_unique<NodeType>(&graph_); - task_runner_->PostTask( - FROM_HERE, base::BindOnce(&Graph::AddNewNode, base::Unretained(&graph_), - base::Unretained(new_node.get()))); +namespace { +// Helper function for adding a node to a graph, and invoking a post-creation +// callback immediately afterwards. +template <typename NodeType> +void AddNodeAndInvokeCreationCallback( + base::OnceCallback<void(NodeType*)> callback, + NodeType* node, + Graph* graph) { + graph->AddNewNode(node); + if (!callback.is_null()) + std::move(callback).Run(node); +} + +} // namespace + +template <typename NodeType, typename... Args> +std::unique_ptr<NodeType> PerformanceManager::CreateNodeImpl( + base::OnceCallback<void(NodeType*)> creation_callback, + Args&&... constructor_args) { + std::unique_ptr<NodeType> new_node = std::make_unique<NodeType>( + &graph_, std::forward<Args>(constructor_args)...); + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&AddNodeAndInvokeCreationCallback<NodeType>, + std::move(creation_callback), + base::Unretained(new_node.get()), + base::Unretained(&graph_))); return new_node; } @@ -161,18 +193,43 @@ std::vector<std::unique_ptr<NodeBase>> nodes) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + base::flat_set<ProcessNodeImpl*> process_nodes; + for (auto it = nodes.begin(); it != nodes.end(); ++it) { - if ((*it)->id().type == resource_coordinator::CoordinationUnitType::kPage) { - auto* page_node = PageNodeImpl::FromNodeBase(it->get()); + switch ((*it)->id().type) { + case resource_coordinator::CoordinationUnitType::kPage: { + auto* page_node = PageNodeImpl::FromNodeBase(it->get()); - // Delete the main frame nodes until no more exist. - while (!page_node->main_frame_nodes().empty()) - RemoveFrameAndChildrenFromGraph( - *(page_node->main_frame_nodes().begin())); + // Delete the main frame nodes until no more exist. + while (!page_node->main_frame_nodes().empty()) + RemoveFrameAndChildrenFromGraph( + *(page_node->main_frame_nodes().begin())); - graph_.RemoveNode(page_node); + graph_.RemoveNode(page_node); + break; + } + case resource_coordinator::CoordinationUnitType::kProcess: { + // Keep track of the process nodes for removing once all frames nodes + // are removed. + auto* process_node = ProcessNodeImpl::FromNodeBase(it->get()); + process_nodes.insert(process_node); + break; + } + case resource_coordinator::CoordinationUnitType::kFrame: + break; + case resource_coordinator::CoordinationUnitType::kSystem: + case resource_coordinator::CoordinationUnitType::kInvalidType: + default: { + NOTREACHED(); + break; + } } } + + // Remove the process nodes from the graph. + for (auto* process_node : process_nodes) + graph_.RemoveNode(process_node); + // When |nodes| goes out of scope, all nodes are deleted. }
diff --git a/chrome/browser/performance_manager/performance_manager.h b/chrome/browser/performance_manager/performance_manager.h index 67ba160..8d8c30b 100644 --- a/chrome/browser/performance_manager/performance_manager.h +++ b/chrome/browser/performance_manager/performance_manager.h
@@ -37,6 +37,8 @@ // {Frame|Page|Process|System}ResourceCoordinator classes. class PerformanceManager { public: + using FrameNodeCreationCallback = base::OnceCallback<void(FrameNodeImpl*)>; + ~PerformanceManager(); // Retrieves the currently registered instance. @@ -63,10 +65,20 @@ void BindInterface(mojo::InterfaceRequest<Interface> request); // Creates a new node of the requested type and adds it to the graph. - // May be called from any sequence. + // May be called from any sequence. If a |creation_callback| is provided it + // will be run on the performance manager sequence immediately after creating + // the node. std::unique_ptr<FrameNodeImpl> CreateFrameNode( + ProcessNodeImpl* process_node, PageNodeImpl* page_node, - FrameNodeImpl* parent_frame_node); + FrameNodeImpl* parent_frame_node, + int frame_tree_node_id); + std::unique_ptr<FrameNodeImpl> CreateFrameNode( + ProcessNodeImpl* process_node, + PageNodeImpl* page_node, + FrameNodeImpl* parent_frame_node, + int frame_tree_node_id, + FrameNodeCreationCallback creation_callback); std::unique_ptr<PageNodeImpl> CreatePageNode(); std::unique_ptr<ProcessNodeImpl> CreateProcessNode(); @@ -95,8 +107,10 @@ void PostBindInterface(const std::string& interface_name, mojo::ScopedMessagePipeHandle message_pipe); - template <typename NodeType> - std::unique_ptr<NodeType> CreateNodeImpl(); + template <typename NodeType, typename... Args> + std::unique_ptr<NodeType> CreateNodeImpl( + base::OnceCallback<void(NodeType*)> creation_callback, + Args&&... constructor_args); void PostDeleteNode(std::unique_ptr<NodeBase> node); void DeleteNodeImpl(std::unique_ptr<NodeBase> node);
diff --git a/chrome/browser/performance_manager/performance_manager_tab_helper.cc b/chrome/browser/performance_manager/performance_manager_tab_helper.cc index 6ddcd77..fe8cda9 100644 --- a/chrome/browser/performance_manager/performance_manager_tab_helper.cc +++ b/chrome/browser/performance_manager/performance_manager_tab_helper.cc
@@ -4,6 +4,7 @@ #include "chrome/browser/performance_manager/performance_manager_tab_helper.h" +#include <type_traits> #include <utility> #include <vector> @@ -50,9 +51,6 @@ UpdatePageNodeVisibility(web_contents->GetVisibility()); // Dispatch creation notifications for any pre-existing frames. - // This seems to occur only in tests, but dealing with this allows asserting - // a strong invariant on the |frames_| collection. - // TODO(siggi): Eliminate this once test injection is all or nothing. std::vector<content::RenderFrameHost*> existing_frames = web_contents->GetAllFrames(); for (content::RenderFrameHost* frame : existing_frames) { @@ -108,22 +106,22 @@ parent_frame_node = frames_[parent].get(); } - std::unique_ptr<FrameNodeImpl> frame = performance_manager_->CreateFrameNode( - page_node_.get(), parent_frame_node); + // Ideally this would strictly be a "Get", but it is possible in tests for + // the the RenderProcessUserData to not have attached at this point. + auto* process_node = RenderProcessUserData::GetOrCreateForRenderProcessHost( + render_frame_host->GetProcess()) + ->process_node(); - RenderProcessUserData* user_data = - RenderProcessUserData::GetForRenderProcessHost( - render_frame_host->GetProcess()); - // In unittests the user data isn't populated as the relevant main parts - // is not in play. - // TODO(siggi): Figure out how to assert on this when the main parts are - // registered with the content browser client. - if (user_data) { - performance_manager_->task_runner()->PostTask( - FROM_HERE, base::BindOnce(&FrameNodeImpl::SetProcess, - base::Unretained(frame.get()), - user_data->process_node())); - } + // Create the frame node, and provide a callback that will run in the graph to + // initialize it. + std::unique_ptr<FrameNodeImpl> frame = performance_manager_->CreateFrameNode( + process_node, page_node_.get(), parent_frame_node, + render_frame_host->GetFrameTreeNodeId(), + base::BindOnce( + [](const GURL& url, FrameNodeImpl* frame_node) { + frame_node->set_url(url); + }, + render_frame_host->GetLastCommittedURL())); frames_[render_frame_host] = std::move(frame); } @@ -138,15 +136,11 @@ } void PerformanceManagerTabHelper::DidStartLoading() { - performance_manager_->task_runner()->PostTask( - FROM_HERE, base::BindOnce(&PageNodeImpl::SetIsLoading, - base::Unretained(page_node_.get()), true)); + PostToGraph(FROM_HERE, &PageNodeImpl::SetIsLoading, page_node_.get(), true); } void PerformanceManagerTabHelper::DidStopLoading() { - performance_manager_->task_runner()->PostTask( - FROM_HERE, base::BindOnce(&PageNodeImpl::SetIsLoading, - base::Unretained(page_node_.get()), false)); + PostToGraph(FROM_HERE, &PageNodeImpl::SetIsLoading, page_node_.get(), false); } void PerformanceManagerTabHelper::OnVisibilityChanged( @@ -176,9 +170,7 @@ // Notify the frame of the committed URL. GURL url = navigation_handle->GetURL(); - performance_manager_->task_runner()->PostTask( - FROM_HERE, base::BindOnce(&FrameNodeImpl::set_url, - base::Unretained(frame_node), url)); + PostToGraph(FROM_HERE, &FrameNodeImpl::set_url, frame_node, url); if (navigation_handle->IsSameDocument() || !navigation_handle->IsInMainFrame()) { @@ -188,11 +180,9 @@ // Make sure the hierarchical structure is constructed before sending signal // to the performance manager. OnMainFrameNavigation(navigation_handle->GetNavigationId()); - performance_manager_->task_runner()->PostTask( - FROM_HERE, base::BindOnce(&PageNodeImpl::OnMainFrameNavigationCommitted, - base::Unretained(page_node_.get()), - navigation_committed_time, - navigation_handle->GetNavigationId(), url)); + PostToGraph(FROM_HERE, &PageNodeImpl::OnMainFrameNavigationCommitted, + page_node_.get(), navigation_committed_time, + navigation_handle->GetNavigationId(), url); } void PerformanceManagerTabHelper::TitleWasSet(content::NavigationEntry* entry) { @@ -201,9 +191,7 @@ first_time_title_set_ = true; return; } - performance_manager_->task_runner()->PostTask( - FROM_HERE, base::BindOnce(&PageNodeImpl::OnTitleUpdated, - base::Unretained(page_node_.get()))); + PostToGraph(FROM_HERE, &PageNodeImpl::OnTitleUpdated, page_node_.get()); } void PerformanceManagerTabHelper::DidUpdateFaviconURL( @@ -213,9 +201,7 @@ first_time_favicon_set_ = true; return; } - performance_manager_->task_runner()->PostTask( - FROM_HERE, base::BindOnce(&PageNodeImpl::OnFaviconUpdated, - base::Unretained(page_node_.get()))); + PostToGraph(FROM_HERE, &PageNodeImpl::OnFaviconUpdated, page_node_.get()); } void PerformanceManagerTabHelper::OnInterfaceRequestFromFrame( @@ -228,21 +214,28 @@ auto it = frames_.find(render_frame_host); DCHECK(it != frames_.end()); + PostToGraph(FROM_HERE, &FrameNodeImpl::AddBinding, it->second.get(), + resource_coordinator::mojom::FrameCoordinationUnitRequest( + std::move(*interface_pipe))); +} + +template <typename Functor, typename NodeType, typename... Args> +void PerformanceManagerTabHelper::PostToGraph(const base::Location& from_here, + Functor&& functor, + NodeType* node, + Args&&... args) { + static_assert(std::is_base_of<NodeBase, NodeType>::value, + "NodeType must be descended from NodeBase"); performance_manager_->task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&FrameNodeImpl::AddBinding, - base::Unretained(it->second.get()), - resource_coordinator::mojom::FrameCoordinationUnitRequest( - std::move(*interface_pipe)))); + from_here, base::BindOnce(functor, base::Unretained(node), + std::forward<Args>(args)...)); } void PerformanceManagerTabHelper::OnMainFrameNavigation(int64_t navigation_id) { ukm_source_id_ = ukm::ConvertToSourceId(navigation_id, ukm::SourceIdType::NAVIGATION_ID); - performance_manager_->task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&PageNodeImpl::SetUkmSourceId, - base::Unretained(page_node_.get()), ukm_source_id_)); + PostToGraph(FROM_HERE, &PageNodeImpl::SetUkmSourceId, page_node_.get(), + ukm_source_id_); first_time_title_set_ = false; first_time_favicon_set_ = false; @@ -252,10 +245,8 @@ content::Visibility visibility) { // TODO(fdoray): An OCCLUDED tab should not be considered visible. const bool is_visible = visibility != content::Visibility::HIDDEN; - performance_manager_->task_runner()->PostTask( - FROM_HERE, - base::BindOnce(&PageNodeImpl::SetIsVisible, - base::Unretained(page_node_.get()), is_visible)); + PostToGraph(FROM_HERE, &PageNodeImpl::SetIsVisible, page_node_.get(), + is_visible); } WEB_CONTENTS_USER_DATA_KEY_IMPL(PerformanceManagerTabHelper)
diff --git a/chrome/browser/performance_manager/performance_manager_tab_helper.h b/chrome/browser/performance_manager/performance_manager_tab_helper.h index b4d2861..4099c1e8 100644 --- a/chrome/browser/performance_manager/performance_manager_tab_helper.h +++ b/chrome/browser/performance_manager/performance_manager_tab_helper.h
@@ -62,13 +62,21 @@ void SetUkmSourceIdForTesting(ukm::SourceId id) { ukm_source_id_ = id; } private: + friend class content::WebContentsUserData<PerformanceManagerTabHelper>; + explicit PerformanceManagerTabHelper(content::WebContents* web_contents); + // Post a task to run in the performance manager sequence. The |node| will be + // passed as unretained, and the closure will be created with BindOnce. + template <typename Functor, typename NodeType, typename... Args> + void PostToGraph(const base::Location& from_here, + Functor&& functor, + NodeType* node, + Args&&... args); + void OnMainFrameNavigation(int64_t navigation_id); void UpdatePageNodeVisibility(content::Visibility visibility); - friend class content::WebContentsUserData<PerformanceManagerTabHelper>; - // The performance manager for this process, if any. PerformanceManager* const performance_manager_; std::unique_ptr<PageNodeImpl> page_node_;
diff --git a/chrome/browser/performance_manager/performance_manager_unittest.cc b/chrome/browser/performance_manager/performance_manager_unittest.cc index b20745f..20e3b491 100644 --- a/chrome/browser/performance_manager/performance_manager_unittest.cc +++ b/chrome/browser/performance_manager/performance_manager_unittest.cc
@@ -53,49 +53,54 @@ }; TEST_F(PerformanceManagerTest, InstantiateNodes) { + std::unique_ptr<ProcessNodeImpl> process_node = + performance_manager()->CreateProcessNode(); + EXPECT_NE(nullptr, process_node.get()); std::unique_ptr<PageNodeImpl> page_node = performance_manager()->CreatePageNode(); EXPECT_NE(nullptr, page_node.get()); // Create a node of each type. std::unique_ptr<FrameNodeImpl> frame_node = - performance_manager()->CreateFrameNode(page_node.get(), nullptr); + performance_manager()->CreateFrameNode(process_node.get(), + page_node.get(), nullptr, 0); EXPECT_NE(nullptr, frame_node.get()); - std::unique_ptr<ProcessNodeImpl> process_node = - performance_manager()->CreateProcessNode(); - EXPECT_NE(nullptr, process_node.get()); - - performance_manager()->DeleteNode(std::move(process_node)); performance_manager()->DeleteNode(std::move(frame_node)); performance_manager()->DeleteNode(std::move(page_node)); + performance_manager()->DeleteNode(std::move(process_node)); } TEST_F(PerformanceManagerTest, BatchDeleteNodes) { // Create a page node and a small hierarchy of frames. + std::unique_ptr<ProcessNodeImpl> process_node = + performance_manager()->CreateProcessNode(); std::unique_ptr<PageNodeImpl> page_node = performance_manager()->CreatePageNode(); std::unique_ptr<FrameNodeImpl> parent1_frame = - performance_manager()->CreateFrameNode(page_node.get(), nullptr); + performance_manager()->CreateFrameNode(process_node.get(), + page_node.get(), nullptr, 0); std::unique_ptr<FrameNodeImpl> parent2_frame = - performance_manager()->CreateFrameNode(page_node.get(), nullptr); + performance_manager()->CreateFrameNode(process_node.get(), + page_node.get(), nullptr, 1); std::unique_ptr<FrameNodeImpl> child1_frame = - performance_manager()->CreateFrameNode(page_node.get(), - parent1_frame.get()); + performance_manager()->CreateFrameNode( + process_node.get(), page_node.get(), parent1_frame.get(), 2); std::unique_ptr<FrameNodeImpl> child2_frame = - performance_manager()->CreateFrameNode(page_node.get(), - parent2_frame.get()); + performance_manager()->CreateFrameNode( + process_node.get(), page_node.get(), parent2_frame.get(), 3); std::vector<std::unique_ptr<NodeBase>> nodes; for (size_t i = 0; i < 10; ++i) { - nodes.push_back(performance_manager()->CreateFrameNode(page_node.get(), - child1_frame.get())); - nodes.push_back(performance_manager()->CreateFrameNode(page_node.get(), - child1_frame.get())); + nodes.push_back(performance_manager()->CreateFrameNode( + process_node.get(), page_node.get(), child1_frame.get(), 0)); + nodes.push_back(performance_manager()->CreateFrameNode( + process_node.get(), page_node.get(), child1_frame.get(), 1)); } + nodes.push_back(std::move(process_node)); nodes.push_back(std::move(page_node)); nodes.push_back(std::move(parent1_frame)); nodes.push_back(std::move(parent2_frame));
diff --git a/chrome/browser/performance_manager/render_process_user_data.cc b/chrome/browser/performance_manager/render_process_user_data.cc index cb10c81..e4780f6 100644 --- a/chrome/browser/performance_manager/render_process_user_data.cc +++ b/chrome/browser/performance_manager/render_process_user_data.cc
@@ -32,10 +32,6 @@ content::RenderProcessHost* render_process_host) : host_(render_process_host), process_node_(PerformanceManager::GetInstance()->CreateProcessNode()) { - // The process itself shouldn't have been created at this point. - DCHECK(!host_->GetProcess().IsValid() || - base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kSingleProcess)); host_->AddObserver(this); // Push this instance to the list. @@ -69,20 +65,26 @@ first_->host_->RemoveUserData(kRenderProcessUserDataKey); } -void RenderProcessUserData::CreateForRenderProcessHost( - content::RenderProcessHost* host) { - std::unique_ptr<RenderProcessUserData> user_data = - base::WrapUnique(new RenderProcessUserData(host)); - - host->SetUserData(kRenderProcessUserDataKey, std::move(user_data)); -} - +// static RenderProcessUserData* RenderProcessUserData::GetForRenderProcessHost( content::RenderProcessHost* host) { return static_cast<RenderProcessUserData*>( host->GetUserData(kRenderProcessUserDataKey)); } +// static +RenderProcessUserData* RenderProcessUserData::GetOrCreateForRenderProcessHost( + content::RenderProcessHost* host) { + auto* raw_user_data = GetForRenderProcessHost(host); + if (raw_user_data) + return raw_user_data; + std::unique_ptr<RenderProcessUserData> user_data = + base::WrapUnique(new RenderProcessUserData(host)); + raw_user_data = user_data.get(); + host->SetUserData(kRenderProcessUserDataKey, std::move(user_data)); + return raw_user_data; +} + void RenderProcessUserData::RenderProcessReady( content::RenderProcessHost* host) { PerformanceManager* performance_manager = PerformanceManager::GetInstance();
diff --git a/chrome/browser/performance_manager/render_process_user_data.h b/chrome/browser/performance_manager/render_process_user_data.h index 18a2554..ac74b1d 100644 --- a/chrome/browser/performance_manager/render_process_user_data.h +++ b/chrome/browser/performance_manager/render_process_user_data.h
@@ -28,9 +28,10 @@ public: ~RenderProcessUserData() override; - static void CreateForRenderProcessHost(content::RenderProcessHost* host); static RenderProcessUserData* GetForRenderProcessHost( content::RenderProcessHost* host); + static RenderProcessUserData* GetOrCreateForRenderProcessHost( + content::RenderProcessHost* host); // Detaches all instances from their RenderProcessHosts and destroys them. static void DetachAndDestroyAll();
diff --git a/chrome/browser/resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.cc b/chrome/browser/resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.cc index d05f4764..08e51b7c 100644 --- a/chrome/browser/resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.cc +++ b/chrome/browser/resource_coordinator/chrome_browser_main_extra_parts_resource_coordinator.cc
@@ -50,8 +50,6 @@ // Release all graph nodes before destroying the performance manager. // First release the browser and GPU process nodes. browser_child_process_watcher_.reset(); - // Then the render process nodes. - performance_manager::RenderProcessUserData::DetachAndDestroyAll(); // There may still be WebContents with attached tab helpers at this point in // time, and there's no convenient later call-out to destroy the performance @@ -59,6 +57,10 @@ // from any existing WebContents. performance_manager::PerformanceManagerTabHelper::DetachAndDestroyAll(); + // Then the render process nodes. These have to be destroyed after the + // frame nodes. + performance_manager::RenderProcessUserData::DetachAndDestroyAll(); + performance_manager::PerformanceManager::Destroy( std::move(performance_manager_)); }
diff --git a/chrome/browser/resources/chromeos/echo/OWNERS b/chrome/browser/resources/chromeos/echo/OWNERS index c197453..d43a12b 100644 --- a/chrome/browser/resources/chromeos/echo/OWNERS +++ b/chrome/browser/resources/chromeos/echo/OWNERS
@@ -1,5 +1,4 @@ -gauravsh@chromium.org jorgelo@chromium.org stephenlin@chromium.org -andycai@chromium.org -oscarpan@chromium.org +abutzier@chromium.org +leecy@chromium.org
diff --git a/chrome/browser/resources/chromeos/echo/manifest.json b/chrome/browser/resources/chromeos/echo/manifest.json index 8297d27..b0efc05 100644 --- a/chrome/browser/resources/chromeos/echo/manifest.json +++ b/chrome/browser/resources/chromeos/echo/manifest.json
@@ -41,7 +41,20 @@ "ids": ["*"], "matches": [ "*://www.google.com/*chromebook/*", - "*://chromebook-dot-googwebreview.appspot.com/*chromebook/*" + "*://www.google.com.au/*chromebook/*", + "*://www.google.ca/*chromebook/*", + "*://www.google.co.jp/*chromebook/*", + "*://www.google.co.uk/*chromebook/*", + "*://www.google.de/*chromebook/*", + "*://www.google.dk/*chromebook/*", + "*://www.google.fi/*chromebook/*", + "*://www.google.fr/*chromebook/*", + "*://www.google.ie/*chromebook/*", + "*://www.google.nl/*chromebook/*", + "*://www.google.no/*chromebook/*", + "*://www.google.co.nz/*chromebook/*", + "*://www.google.se/*chromebook/*", + "*://chromebook*-dot-googwebreview.appspot.com/*chromebook/*" ] } }
diff --git a/chrome/browser/resources/chromeos/login/BUILD.gn b/chrome/browser/resources/chromeos/login/BUILD.gn index 3425340..b3149962 100644 --- a/chrome/browser/resources/chromeos/login/BUILD.gn +++ b/chrome/browser/resources/chromeos/login/BUILD.gn
@@ -11,6 +11,26 @@ ":offline_ad_login", ":oobe_change_picture", ":oobe_select", + ":oobe_welcome", + ] +} + +js_library("oobe_types") { +} + +# This is special file to be used as a substutute of Oobe object for closure +# compilation until we make real one closure compile. +# TODO (https://crbug.com/950198) +js_library("fake_oobe") { + deps = [ + ":oobe_types", + ] +} + +js_library("login_screen_behavior") { + deps = [ + ":fake_oobe", + "//ui/login:display_manager_types", ] } @@ -20,6 +40,12 @@ js_library("oobe_select") { } +js_library("oobe_welcome") { + deps = [ + ":login_screen_behavior", + ] +} + js_library("offline_ad_login") { deps = [ ":oobe_dialog_host_behavior",
diff --git a/chrome/browser/resources/chromeos/login/fake_oobe.js b/chrome/browser/resources/chromeos/login/fake_oobe.js new file mode 100644 index 0000000..e1a5b94 --- /dev/null +++ b/chrome/browser/resources/chromeos/login/fake_oobe.js
@@ -0,0 +1,54 @@ +// Copyright 2019 The Chromium 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 Fake out of the box experience flow (OOBE) for + * closure_compiler coverage. + */ + +/** @typedef {string} */ +var ACCELERATOR_ENABLE_DEBBUGING = '1'; + +/** @typedef {string} */ +var ACCELERATOR_DEVICE_REQUISITION_REMORA = '2'; + +/** @typedef {string} */ +var ACCELERATOR_DEVICE_REQUISITION = '3'; + +var cr; +cr.ui = {}; + +cr.define = function(name, constructor_function) {}; + +/** @interface */ +class Oobe { + constructor() {} + + /** @return {Oobe} */ + getInstance() {} + + /** + * @param { + * ACCELERATOR_ENABLE_DEBBUGING | + * ACCELERATOR_DEVICE_REQUISITION_REMORA | + * ACCELERATOR_DEVICE_REQUISITION + * } accelerator + */ + handleAccelerator(accelerator) {} + + /** + * @param {Element} el Decorated screen element. + * @param {DisplayManagerScreenAttributes} attributes + */ + registerScreen(el, attributes) {} + + /** + * @return {?OobeTypes.OobeConfiguration} + */ + getOobeConfiguration() {} + + startDemoModeFlow() {} +} + +cr.ui.Oobe = Oobe;
diff --git a/chrome/browser/resources/chromeos/login/login_screen_behavior.js b/chrome/browser/resources/chromeos/login/login_screen_behavior.js index 7deb31b..fa8b2cf 100644 --- a/chrome/browser/resources/chromeos/login/login_screen_behavior.js +++ b/chrome/browser/resources/chromeos/login/login_screen_behavior.js
@@ -7,8 +7,6 @@ * 'LoginScreenBehavior' is login.Screen API implementation for Polymer objects. */ -// <include src="../../../../../ui/login/display_manager_types.js"> - /** @polymerBehavior */ var LoginScreenBehavior = { // List of methods exported to login.screenName.<method> API. @@ -71,34 +69,34 @@ /** * Screen will ignore accelerators when true. - * @type {Boolean} + * @type {boolean} */ ignoreAccelerators: false, /** * If defined, invoked for the currently active screen when screen size * changes. - * @type{function()} + * @type {function()|undefined} */ onWindowResize: undefined, /** * If defined, invoked when tablet mode is changed. * Boolean parameter is true when device is in tablet mode. - * @type {function(Boolean)} + * @type {function(boolean)|undefined} */ setTabletModeState: undefined, /** * If defined, invoked for the currently active screen when screen localized * data needs to be updated. - * @type{function()} + * @type {function()|undefined} */ updateLocalizedContent: undefined, /** * If defined, invoked when OOBE configuration is loaded. - * @param {!OobeTypes.OobeConfiguration} configuration + * @type {OobeTypes.OobeConfiguration|undefined} configuration */ updateOobeConfiguration: undefined, @@ -111,11 +109,12 @@ * login.ScreenName.foo(); // valid * * @param {string} name Name of created class. - * @param {Object} id Id of div representing screen. + * @param {Object} api Screen API. * @private */ registerScreenApi_: function(name, api) { - cr.define('login', function() { + // Closure compiler incorrectly parses this, so we use cr.define.call(...). + cr.define.call(cr.define, 'login', function() { var result = {}; result[name] = api; return result;
diff --git a/chrome/browser/resources/chromeos/login/oobe_select.js b/chrome/browser/resources/chromeos/login/oobe_select.js index f0b648d0..a90d571d 100644 --- a/chrome/browser/resources/chromeos/login/oobe_select.js +++ b/chrome/browser/resources/chromeos/login/oobe_select.js
@@ -6,7 +6,16 @@ * @fileoverview Helper functions to manage select UI elements. */ -/** @typedef {Iterable<{value: string, title: string, selected: boolean}>} */ +/** + * @typedef { + * Iterable<{ + * optionGroupName: (string|undefined), + * selected: boolean, + * title: string, + * value: string, + * }> + * } + */ var SelectListType; /**
diff --git a/chrome/browser/resources/chromeos/login/oobe_types.js b/chrome/browser/resources/chromeos/login/oobe_types.js index a621c4c..7ca2ac39 100644 --- a/chrome/browser/resources/chromeos/login/oobe_types.js +++ b/chrome/browser/resources/chromeos/login/oobe_types.js
@@ -13,10 +13,14 @@ /** * ChromeOS OOBE language descriptor. * @typedef {{ - * code: (String|undefined), - * displayName: (String|undefined), - * textDirection: (String|undefined), - * nativeDisplayName: (String|undefined), + * code: (string|undefined), + * displayName: (string|undefined), + * nativeDisplayName: (string|undefined), + * optionGroupName: (string|undefined), + * selected: boolean, + * textDirection: (string|undefined), + * title: string, + * value: string, * }} */ OobeTypes.LanguageDsc; @@ -24,9 +28,10 @@ /** * ChromeOS OOBE input method descriptor. * @typedef {{ - * value: (String|undefined), - * title: (String|undefined), - * selected: (Boolean|undefined), + * optionGroupName: (string|undefined), + * selected: boolean, + * title: string, + * value: string, * }} */ OobeTypes.IMEDsc; @@ -34,9 +39,9 @@ /** * ChromeOS OOBE demo country descriptor. * @typedef {{ - * value: (String|undefined), - * title: (String|undefined), - * selected: (Boolean|undefined), + * value: (string|undefined), + * title: (string|undefined), + * selected: (boolean|undefined), * }} */ OobeTypes.DemoCountryDsc; @@ -44,11 +49,11 @@ /** * A set of flags of accessibility options for ChromeOS OOBE. * @typedef {{ - * highContrastEnabled: Boolean, - * spokenFeedbackEnabled: Boolean, - * screenMagnifierEnabled: Boolean, - * largeCursorEnabled: Boolean, - * virtualKeyboardEnabled: Boolean, + * highContrastEnabled: boolean, + * spokenFeedbackEnabled: boolean, + * screenMagnifierEnabled: boolean, + * largeCursorEnabled: boolean, + * virtualKeyboardEnabled: boolean, * }} */ OobeTypes.A11yStatuses; @@ -70,7 +75,7 @@ * @typedef {{ * value: (OobeTypes.Timezone|undefined), * title: (String|undefined), - * selected: (Boolean|undefined), + * selected: (boolean|undefined), * }} */ OobeTypes.TimezoneDsc; @@ -79,18 +84,18 @@ * OOBE configuration, allows automation during OOBE. * Keys are also listed in chrome/browser/chromeos/login/configuration_keys.h * @typedef {{ - * language: string|undefined, - * inputMethod: string|undefined, - * welcomeNext: boolean|undefined, - * enableDemoMode: boolean|undefined, - * demoPreferencesNext: boolean|undefined, - * networkSelectGuid: string|undefined, - * networkOfflineDemo: boolean|undefined, - * eulaAutoAccept: boolean|undefined, - * eulaSendStatistics: boolean|undefined, - * networkUseConnected: boolean|undefined, - * updateSkipNonCritical: boolean|undefined, - * arcTosAutoAccept: boolean|undefined, + * language: (string|undefined), + * inputMethod: (string|undefined), + * welcomeNext: (boolean|undefined), + * enableDemoMode: (boolean|undefined), + * demoPreferencesNext: (boolean|undefined), + * networkSelectGuid: (string|undefined), + * networkOfflineDemo: (boolean|undefined), + * eulaAutoAccept: (boolean|undefined), + * eulaSendStatistics: (boolean|undefined), + * networkUseConnected: (boolean|undefined), + * updateSkipNonCritical: (boolean|undefined), + * arcTosAutoAccept: (boolean|undefined), * }} */ OobeTypes.OobeConfiguration;
diff --git a/chrome/browser/resources/chromeos/login/oobe_welcome.js b/chrome/browser/resources/chromeos/login/oobe_welcome.js index 7b3e273..dc785b88 100644 --- a/chrome/browser/resources/chromeos/login/oobe_welcome.js +++ b/chrome/browser/resources/chromeos/login/oobe_welcome.js
@@ -77,7 +77,7 @@ debuggingLinkVisible_: Boolean, }, - /** @override */ + /** Overridden from LoginScreenBehavior. */ EXTERNAL_API: [ 'onInputMethodIdSetFromBackend', ], @@ -131,13 +131,17 @@ /** * This is called when UI strings are changed. - * @override + * Overridden from LoginScreenBehavior. */ updateLocalizedContent: function() { - this.languages = loadTimeData.getValue('languageList'); - this.keyboards = loadTimeData.getValue('inputMethodsList'); - this.timezones = loadTimeData.getValue('timezoneList'); - this.highlightStrength = loadTimeData.getValue('highlightStrength'); + this.languages = /** @type {!Array<OobeTypes.LanguageDsc>} */ ( + loadTimeData.getValue('languageList')); + this.keyboards = /** @type {!Array<OobeTypes.IMEDsc>} */ ( + loadTimeData.getValue('inputMethodsList')); + this.timezones = /** @type {!Array<OobeTypes.TimezoneDsc>} */ ( + loadTimeData.getValue('timezoneList')); + this.highlightStrength = + /** @type {string} */ (loadTimeData.getValue('highlightStrength')); this.$.welcomeScreen.i18nUpdateLocale(); this.i18nUpdateLocale(); @@ -156,8 +160,8 @@ /** * Called when OOBE configuration is loaded. + * Overridden from LoginScreenBehavior. * @param {!OobeTypes.OobeConfiguration} configuration - * @override */ updateOobeConfiguration: function(configuration) { if (!this.configuration_applied_) @@ -199,8 +203,8 @@ /** * Updates "device in tablet mode" state when tablet mode is changed. - * @param {Boolean} isInTabletMode True when in tablet mode. - * @override + * Overridden from LoginScreenBehavior. + * @param {boolean} isInTabletMode True when in tablet mode. */ setTabletModeState: function(isInTabletMode) { this.$.welcomeScreen.isInTabletMode = isInTabletMode; @@ -343,7 +347,7 @@ /** * Switch UI language. * - * @param {!OobeTypes.LanguageDsc} languageId + * @param {string} languageId * @private */ applySelectedLanguage_: function(languageId) { @@ -366,7 +370,7 @@ /** * Switch keyboard layout. * - * @param {!OobeTypes.IMEDsc} inputMethodId + * @param {string} inputMethodId * @private */ applySelectedLkeyboard_: function(inputMethodId) { @@ -374,7 +378,8 @@ }, onLanguagesChanged_: function() { - this.currentLanguage = getSelectedTitle(this.languages); + this.currentLanguage = + getSelectedTitle(/** @type {!SelectListType} */ (this.languages)); }, onInputMethodIdSetFromBackend: function(keyboard_id) { @@ -428,8 +433,9 @@ * @param {!Event} event */ onA11yOptionChanged_: function(event) { - chrome.send( - event.currentTarget.chromeMessage, [event.currentTarget.checked]); + var a11ytarget = /** @type {{chromeMessage: string, checked: boolean}} */ ( + event.currentTarget); + chrome.send(a11ytarget.chromeMessage, [a11ytarget.checked]); }, /** ******************** Timezone section ******************* */
diff --git a/chrome/browser/resources/print_preview/new/button_strip.html b/chrome/browser/resources/print_preview/new/button_strip.html index 917c067..60fdc03 100644 --- a/chrome/browser/resources/print_preview/new/button_strip.html +++ b/chrome/browser/resources/print_preview/new/button_strip.html
@@ -17,9 +17,9 @@ display: flex; flex-direction: row; justify-content: flex-end; - margin-top: 16px; padding-bottom: 16px; padding-inline-end: 16px; + padding-top: 16px; } :host-context(html:not([dark])) {
diff --git a/chrome/browser/resources/print_preview/new/link_container.html b/chrome/browser/resources/print_preview/new/link_container.html index 98f9072..c816839 100644 --- a/chrome/browser/resources/print_preview/new/link_container.html +++ b/chrome/browser/resources/print_preview/new/link_container.html
@@ -9,6 +9,10 @@ <dom-module id="print-preview-link-container"> <template> <style include="print-preview-shared throbber cr-hidden-style"> + :host { + display: block; + } + :host paper-icon-button-light { --cr-paper-icon-button-margin: { margin-inline-end: -2px; @@ -36,7 +40,6 @@ } #systemDialogLink { - border-top: var(--print-preview-settings-border); padding-top: 0.5em; }
diff --git a/chrome/browser/resources/print_preview/new/print_preview_sidebar.html b/chrome/browser/resources/print_preview/new/print_preview_sidebar.html index 4e4ad7d..ec82d93 100644 --- a/chrome/browser/resources/print_preview/new/print_preview_sidebar.html +++ b/chrome/browser/resources/print_preview/new/print_preview_sidebar.html
@@ -60,11 +60,24 @@ margin-top: 12px; } + /* Print Preview uses lighter box-shadows compared to the default + * styling. */ + :host([new-print-preview-layout_]) #cr-container-shadow-top, + :host([new-print-preview-layout_]) #cr-container-shadow-bottom { + box-shadow: inset 0 5px 3px -3px rgba(0, 0, 0, .2); + } + .settings-section { display: block; margin-bottom: 16px; margin-top: 16px; } + +<if expr="not chromeos"> + :host(:not([new-print-preview-layout_])) print-preview-link-container { + border-top: var(--print-preview-settings-border); + } +</if> </style> <template is="dom-if" if="[[newPrintPreviewLayout_]]"> <print-preview-header-new id="header" destination="[[destination]]" @@ -80,7 +93,7 @@ settings="[[settings]]" managed="[[controlsManaged]]"> </print-preview-header> </template> - <div id="container"> + <div id="container" show-bottom-shadow$="[[newPrintPreviewLayout_]]"> <print-preview-destination-settings id="destinationSettings" cloud-print-interface="[[cloudPrintInterface]]" destination="{{destination}}" destination-state="{{destinationState}}" @@ -155,12 +168,22 @@ hidden$="[[!settings.vendorItems.available]]" class="settings-section"> </print-preview-advanced-options-settings> +<if expr="not chromeos"> + <template is="dom-if" if="[[newPrintPreviewLayout_]]"> + <print-preview-link-container destination="[[destination]]" + app-kiosk-mode="[[isInAppKioskMode_]]" + disabled="[[controlsDisabled_]]"> + </print-preview-link-container> + </template> +</if> </iron-collapse> <if expr="not chromeos"> + <template is="dom-if" if="[[!newPrintPreviewLayout_]]"> <print-preview-link-container destination="[[destination]]" app-kiosk-mode="[[isInAppKioskMode_]]" disabled="[[controlsDisabled_]]"> </print-preview-link-container> + </template> </if> </div> <template is="dom-if" if="[[newPrintPreviewLayout_]]">
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html b/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html index d8b7649..87a747d 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/ntp_background/nux_ntp_background.html
@@ -9,6 +9,7 @@ <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html"> <link rel="import" href="../navigation_behavior.html"> +<link rel="import" href="../shared/chooser_shared_css.html"> <link rel="import" href="../shared/i18n_setup.html"> <link rel="import" href="../shared/module_metrics_proxy.html"> <link rel="import" href="../shared/step_indicator.html"> @@ -16,7 +17,7 @@ <dom-module id="nux-ntp-background"> <template> - <style include="paper-button-style"> + <style include="chooser-shared-css paper-button-style"> :host { text-align: center; } @@ -40,7 +41,7 @@ #backgroundPreview::before { /* Copied from browser/resources/local_ntp/custom_backgrounds.js */ - background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.3)); + background-image: linear-gradient(rgba(0, 0, 0, 0), rgba(0, 0, 0, .3)); /* Pseudo element needs some content (even an empty string) to be * displayed. */ content: ''; @@ -90,15 +91,10 @@ width: 592px; } - .ntp-background-grid-button { + .option { align-items: stretch; - background: var(--cr-card-background-color); - border: solid 1px var(--google-grey-refresh-300); border-radius: 4px; - color: var(--cr-secondary-text-color); - cursor: pointer; display: flex; - flex-direction: column; height: 100%; overflow: hidden; padding: 0; @@ -107,27 +103,52 @@ width: 100%; } - #backgroundPreview.active + .content .ntp-background-grid-button { + #backgroundPreview.active + .content .option { border-color: var(--google-grey-refresh-700); } - .ntp-background-grid-button:hover { - box-shadow: 0 3px 6px 2px rgba(0, 36, 100, .1); - } - /* Remove outline when button is focused using the mouse. */ - .ntp-background-grid-button:focus:not(.keyboard-focused) { + .option:focus:not(.keyboard-focused) { outline: none; } .ntp-background-thumbnail { - background-color: white; + background-color: var(--cr-card-background-color); background-position: center center; background-repeat: no-repeat; background-size: cover; flex: 1; } + .option-name { + border-top: var(--cr-separator-line); + color: var(--navi-wallpaper-text-color); + height: 3rem; + line-height: 3rem; + overflow: hidden; + padding: 0 .75rem; + text-overflow: ellipsis; + } + + .option[active] .option-name { + background: var(--cr-checked-color); + color: var(--cr-card-background-color); + } + + .button-bar { + margin-top: 56px; + } + + #skipButton { + background-color: var(--cr-card-background-color) + } + + #skipButton:hover { + background-image: + linear-gradient(var(--hover-bg-color), var(--hover-bg-color)); + } + + /* Wallpaper Thumbnails */ .art { background-image: url(../images/ntp_thumbnails/art.jpg); } @@ -147,43 +168,6 @@ .landscape { background-image: url(../images/ntp_thumbnails/landscape.jpg); } - - .ntp-background-title { - border-top: var(--cr-separator-line); - font-size: 14px; - height: 48px; - line-height: 48px; - overflow: hidden; - padding: 0 12px; - text-overflow: ellipsis; - } - - .ntp-background-grid-button[active] .ntp-background-title { - background: var(--google-blue-600); - color: white; - } - - .button-bar { - display: flex; - justify-content: space-between; - margin-top: 56px; - } - - .skip-button-container { - background: white; - border-radius: 4px; - } - - iron-icon[icon='cr:chevron-right'] { - height: 20px; - margin-inline-end: -10px; - margin-inline-start: 6px; - width: 20px; - } - - :host-context([dir=rtl]) iron-icon { - transform: scaleX(-1); - } </style> <div id="backgroundPreview" @@ -198,24 +182,22 @@ <template is="dom-repeat" items="[[backgrounds_]]"> <button active$="[[isSelectedBackground_(item, selectedBackground_)]]" - class="ntp-background-grid-button" + class="option" on-click="onBackgroundClick_" on-keyup="onBackgroundKeyUp_" on-pointerdown="onBackgroundPointerDown_"> <div class$="ntp-background-thumbnail [[item.thumbnailClass]]"> </div> - <div class="ntp-background-title">[[item.title]]</div> + <div class="option-name">[[item.title]]</div> </button> </template> </div> <div class="button-bar"> - <div class="skip-button-container"> - <paper-button id="skipButton" on-click="onSkipClicked_"> - $i18n{skip} - </paper-button> - </div> + <paper-button id="skipButton" on-click="onSkipClicked_"> + $i18n{skip} + </paper-button> <step-indicator model="[[indicatorModel]]"></step-indicator> <paper-button class="action-button" on-click="onNextClicked_">
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/app_chooser.html b/chrome/browser/resources/welcome/onboarding_welcome/shared/app_chooser.html index 5ad293f..11a9b56 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/shared/app_chooser.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/app_chooser.html
@@ -19,6 +19,100 @@ <dom-module id="app-chooser"> <template> <style include="chooser-shared-css paper-button-style"> + :host { + display: block; + white-space: nowrap; + } + + .button-bar { + margin-top: 4rem; + } + + .option { + -webkit-appearance: none; + align-items: center; + border-radius: 8px; + box-sizing: border-box; + display: inline-flex; + font-family: inherit; + height: 7.5rem; + justify-content: center; + outline: 0; + position: relative; + transition-duration: 500ms; + transition-property: box-shadow; + vertical-align: bottom; + width: 6.25rem; + } + + .option:not(:first-of-type) { + margin-inline-start: 1.5rem; + } + + .option[active] { + border: 1px solid var(--cr-checked-color); + color: var(--cr-checked-color); + font-weight: 500; + } + + .option.keyboard-focused:focus { + outline: var(--navi-keyboard-focus-color) solid 3px; + } + + .option-name { + flex-grow: 0; + line-height: 1.25rem; + text-align: center; + white-space: normal; + } + + .option-icon { + background-position: center; + background-repeat: no-repeat; + background-size: contain; + height: 2rem; + margin: auto; + width: 2rem; + } + + .option-icon-shadow { + background-color: var(--navi-option-icon-shadow-color); + border-radius: 50%; + display: flex; + height: 3rem; + margin-bottom: .25rem; + width: 3rem; + } + + .option iron-icon { + --iron-icon-fill-color: var(--cr-card-background-color); + background: var(--navi-check-icon-color); + border-radius: 50%; + display: none; + height: .75rem; + margin: 0; + position: absolute; + right: .375rem; + top: .375rem; + width: .75rem; + } + + :host-context([dir=rtl]) .option iron-icon { + left: .375rem; + right: unset; + } + + .option.keyboard-focused:focus iron-icon[icon='cr:check'], + .option:hover iron-icon[icon='cr:check'], + .option[active] iron-icon[icon='cr:check'] { + display: block; + } + + .option[active] iron-icon[icon='cr:check'] { + background: var(--cr-checked-color); + } + + /* App Icons */ .gmail { content: -webkit-image-set( url(chrome://welcome/images/gmail_1x.png) 1x,
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html b/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html index 5a0687fa..97449a2 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/chooser_shared_css.html
@@ -7,109 +7,25 @@ <dom-module id="chooser-shared-css"> <template> <style include="navi-colors-css"> - :host { - display: block; - white-space: nowrap; - } - .option { - -webkit-appearance: none; - align-items: center; background: var(--cr-card-background-color); border: 1px solid var(--navi-border-color); - border-radius: 8px; - box-sizing: border-box; color: var(--cr-primary-text-color); cursor: pointer; - display: inline-flex; flex-direction: column; - font-family: inherit; - height: 7.5rem; - justify-content: center; - outline: 0; - position: relative; - transition-duration: 500ms; - transition-property: box-shadow; - vertical-align: bottom; - width: 6.25rem; } .option:hover { box-shadow: var(--navi-option-box-shadow); } - .option[active] { - border: 1px solid var(--cr-checked-color); - color: var(--cr-checked-color); - font-weight: 500; - } - - .option:not(:first-of-type) { - margin-inline-start: 1.5rem; - } - - .option.keyboard-focused:focus { - outline: var(--navi-keyboard-focus-color) solid 3px; - } - - .option .option-name { - flex-grow: 0; - font-size: 0.875rem; - line-height: 1.25rem; - text-align: center; - white-space: normal; - } - - .option .option-icon { - background-position: center; - background-repeat: no-repeat; - background-size: contain; - height: 2rem; - margin: auto; - width: 2rem; - } - - .option .option-icon-shadow { - background-color: var(--navi-option-icon-shadow-color); - border-radius: 50%; - display: flex; - height: 3rem; - margin-bottom: 0.25rem; - width: 3rem; - } - - :host-context([dir=rtl]) .option iron-icon { - left: 0.375rem; - right: unset; - } - - .option iron-icon { - --iron-icon-fill-color: var(--cr-card-background-color); - background: var(--navi-check-icon-color); - border-radius: 50%; - display: none; - height: 0.75rem; - margin: 0; - position: absolute; - right: 0.375rem; - top: 0.375rem; - width: 0.75rem; - } - - .option.keyboard-focused:focus iron-icon[icon='cr:check'], - .option:hover iron-icon[icon='cr:check'], - .option[active] iron-icon[icon='cr:check'] { - display: block; - } - - .option[active] iron-icon[icon='cr:check'] { - background: var(--cr-checked-color); + .option-name { + font-size: .875rem; } .button-bar { display: flex; justify-content: space-between; - margin-top: 4rem; } :host-context([dir=rtl]) iron-icon[icon='cr:chevron-right'] { @@ -118,8 +34,8 @@ iron-icon[icon='cr:chevron-right'] { height: 1.25rem; - margin-inline-end: -0.625rem; - margin-inline-start: 0.375rem; + margin-inline-end: -.625rem; + margin-inline-start: .375rem; width: 1.25rem; } </style>
diff --git a/chrome/browser/resources/welcome/onboarding_welcome/shared/navi_colors_css.html b/chrome/browser/resources/welcome/onboarding_welcome/shared/navi_colors_css.html index 2970436..66c0fd8 100644 --- a/chrome/browser/resources/welcome/onboarding_welcome/shared/navi_colors_css.html +++ b/chrome/browser/resources/welcome/onboarding_welcome/shared/navi_colors_css.html
@@ -25,6 +25,7 @@ opacity: .5; /* Only in light mode */ }; --navi-step-indicator-color: var(--google-grey-200); + --navi-wallpaper-text-color: var(--google-grey-refresh-700); } :host-context([dark]) { @@ -45,6 +46,7 @@ background: var(--google-blue-refresh-300); }; --navi-step-indicator-color: var(--google-grey-refresh-500); + --navi-wallpaper-text-color: var(--google-grey-200); } </style> </template>
diff --git a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc index 21d0f69..4995b84 100644 --- a/chrome/browser/ui/bookmarks/bookmark_browsertest.cc +++ b/chrome/browser/ui/bookmarks/bookmark_browsertest.cc
@@ -7,6 +7,7 @@ #include "base/macros.h" #include "base/strings/utf_string_conversions.h" #include "base/test/bind_test_util.h" +#include "base/test/metrics/histogram_tester.h" #include "base/timer/timer.h" #include "build/build_config.h" #include "chrome/app/chrome_command_ids.h" @@ -35,6 +36,7 @@ #include "content/public/browser/web_contents.h" #include "content/public/test/browser_test_utils.h" #include "net/test/embedded_test_server/embedded_test_server.h" +#include "testing/gmock/include/gmock/gmock.h" #include "ui/base/dragdrop/os_exchange_data.h" #include "ui/gfx/image/image_skia.h" @@ -115,7 +117,13 @@ return bookmark_model; } + base::HistogramTester* histogram_tester() { return &histogram_tester_; } + private: + // We make the histogram tester a member field to make sure it starts + // recording as early as possible. + base::HistogramTester histogram_tester_; + DISALLOW_COPY_AND_ASSIGN(BookmarkBrowsertest); }; @@ -315,3 +323,66 @@ run_loop->Run(); } + +// ChromeOS initializes two profiles (Default and test-user) and it's impossible +// to distinguish UMA samples separately. +#if !defined(OS_CHROMEOS) + +IN_PROC_BROWSER_TEST_F(BookmarkBrowsertest, PRE_EmitUmaForDuplicates) { + BookmarkModel* bookmark_model = WaitForBookmarkModel(browser()->profile()); + const BookmarkNode* parent = bookmarks::GetParentForNewNodes(bookmark_model); + // Add one bookmark with a unique URL, two other bookmarks with a shared URL, + // and three more with another shared URL. + bookmark_model->AddURL(parent, parent->child_count(), + base::ASCIIToUTF16("title1"), GURL("http://a.com")); + bookmark_model->AddURL(parent, parent->child_count(), + base::ASCIIToUTF16("title2"), GURL("http://b.com")); + bookmark_model->AddURL(parent, parent->child_count(), + base::ASCIIToUTF16("title3"), GURL("http://b.com")); + bookmark_model->AddURL(parent, parent->child_count(), + base::ASCIIToUTF16("title4"), GURL("http://c.com")); + bookmark_model->AddURL(parent, parent->child_count(), + base::ASCIIToUTF16("title5"), GURL("http://c.com")); + bookmark_model->AddURL(parent, parent->child_count(), + base::ASCIIToUTF16("title6"), GURL("http://c.com")); +} + +IN_PROC_BROWSER_TEST_F(BookmarkBrowsertest, EmitUmaForDuplicates) { + WaitForBookmarkModel(browser()->profile()); + + ASSERT_THAT( + histogram_tester()->GetAllSamples("Bookmarks.Count.OnProfileLoad"), + testing::ElementsAre(base::Bucket(/*min=*/6, /*count=*/1))); + EXPECT_THAT(histogram_tester()->GetAllSamples( + "Bookmarks.Count.OnProfileLoad.DuplicateUrl"), + testing::ElementsAre(base::Bucket(/*min=*/5, /*count=*/1))); +} + +IN_PROC_BROWSER_TEST_F(BookmarkBrowsertest, PRE_EmitUmaForEmptyTitles) { + BookmarkModel* bookmark_model = WaitForBookmarkModel(browser()->profile()); + const BookmarkNode* parent = bookmarks::GetParentForNewNodes(bookmark_model); + // Add two bookmarks with a non-empty title and three with an empty one. + bookmark_model->AddURL(parent, parent->child_count(), + base::ASCIIToUTF16("title1"), GURL("http://a.com")); + bookmark_model->AddURL(parent, parent->child_count(), + base::ASCIIToUTF16("title2"), GURL("http://b.com")); + bookmark_model->AddURL(parent, parent->child_count(), base::string16(), + GURL("http://c.com")); + bookmark_model->AddURL(parent, parent->child_count(), base::string16(), + GURL("http://d.com")); + bookmark_model->AddURL(parent, parent->child_count(), base::string16(), + GURL("http://e.com")); +} + +IN_PROC_BROWSER_TEST_F(BookmarkBrowsertest, EmitUmaForEmptyTitles) { + WaitForBookmarkModel(browser()->profile()); + + ASSERT_THAT( + histogram_tester()->GetAllSamples("Bookmarks.Count.OnProfileLoad"), + testing::ElementsAre(base::Bucket(/*min=*/5, /*count=*/1))); + EXPECT_THAT(histogram_tester()->GetAllSamples( + "Bookmarks.Count.OnProfileLoad.EmptyTitle"), + testing::ElementsAre(base::Bucket(/*min=*/3, /*count=*/1))); +} + +#endif // !defined(OS_CHROMEOS)
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc index 3c7c75b..c7964ef 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_browsertest.cc
@@ -153,10 +153,10 @@ } { - // Sec-Fetch-User: ?T + // Sec-Fetch-User: ?1 CreateBookmarkForHeader("Sec-Fetch-User"); NavigateToBookmark(); - EXPECT_EQ("?T", GetContent()); + EXPECT_EQ("?1", GetContent()); } } @@ -187,9 +187,9 @@ } { - // Sec-Fetch-User: ?T + // Sec-Fetch-User: ?1 CreateBookmarkForHeader("Sec-Fetch-User"); NavigateToBookmark(); - EXPECT_EQ("?T", GetContent()); + EXPECT_EQ("?1", GetContent()); } }
diff --git a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc index e9cbb44804..d88d6b8 100644 --- a/chrome/browser/ui/views/payments/payment_request_dialog_view.cc +++ b/chrome/browser/ui/views/payments/payment_request_dialog_view.cc
@@ -85,6 +85,11 @@ ++number_of_initialization_tasks_; } + if (!request->spec()->IsInitialized()) { + request->spec()->AddInitializationObserver(this); + ++number_of_initialization_tasks_; + } + if (number_of_initialization_tasks_ > 0) { ShowProcessingSpinner(); } else if (observer_for_testing_) {
diff --git a/chrome/browser/ui/views/payments/payment_request_show_promise_browsertest.cc b/chrome/browser/ui/views/payments/payment_request_show_promise_browsertest.cc new file mode 100644 index 0000000..5b0eebff --- /dev/null +++ b/chrome/browser/ui/views/payments/payment_request_show_promise_browsertest.cc
@@ -0,0 +1,334 @@ +// Copyright 2019 The Chromium 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/strings/utf_string_conversions.h" +#include "build/build_config.h" +#include "chrome/browser/ui/views/payments/payment_request_browsertest_base.h" +#include "chrome/browser/ui/views/payments/payment_request_dialog_view_ids.h" +#include "components/autofill/core/browser/autofill_profile.h" +#include "components/autofill/core/browser/autofill_test_utils.h" +#include "components/web_modal/web_contents_modal_dialog_manager.h" +#include "content/public/test/browser_test_utils.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "ui/views/controls/label.h" +#include "ui/views/view.h" + +namespace payments { +namespace { + +class PaymentRequestShowPromiseTest : public PaymentRequestBrowserTestBase { + protected: + PaymentRequestShowPromiseTest() {} + ~PaymentRequestShowPromiseTest() override {} + + // Installs the payment handler for "basic-card" that responds to + // "paymentrequest" events by echoing back the "total" object. + void InstallEchoPaymentHandlerForBasicCard() { + std::string contents; + ASSERT_TRUE(content::ExecuteScriptAndExtractString( + GetActiveWebContents(), "install();", &contents)); + ASSERT_EQ(contents, "instruments.set(): Payment handler installed."); + } + + // Allows to skip UI into payment handler for "basic-card". + void EnalbeSkipUIForForBasicCard() { + std::vector<PaymentRequest*> requests = + GetPaymentRequests(GetActiveWebContents()); + ASSERT_EQ(1U, requests.size()); + requests.front() + ->set_skip_ui_for_non_url_payment_method_identifiers_for_test(); + } + + // Shows the browser payment sheet. + void ShowBrowserPaymentSheet() { + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::SPEC_DONE_UPDATING, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::DIALOG_OPENED}); + ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); + WaitForObservedEvent(); + EXPECT_TRUE(web_modal::WebContentsModalDialogManager::FromWebContents( + GetActiveWebContents()) + ->IsDialogActive()); + } + + // Verifies that the payment sheet total is |total_amount_string|. + void ExpectTotal(const std::string& total_amount_string) { + EXPECT_EQ(base::ASCIIToUTF16(total_amount_string), + GetLabelText(DialogViewID::ORDER_SUMMARY_TOTAL_AMOUNT_LABEL)); + } + + // Verifies that the shipping address section does not display any warning + // messages. + void ExpectNoShippingWarningMessage() { + views::View* view = dialog_view()->GetViewByID( + static_cast<int>(DialogViewID::WARNING_LABEL)); + if (!view || !view->visible()) + return; + + EXPECT_EQ(base::string16(), static_cast<views::Label*>(view)->text()); + } + + // Verifies that the shipping address section has |expected_message| in the + // header. + void ExpectShippingWarningMessage(const std::string& expected_message) { + EXPECT_EQ(base::ASCIIToUTF16(expected_message), + GetLabelText(DialogViewID::WARNING_LABEL)); + } + + // Selects another shipping address. + void SelectAnotherShippingAddress() { + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::SPEC_DONE_UPDATING}); + ClickOnChildInListViewAndWait( + /*child_index=*/1, /*total_num_children=*/2, + DialogViewID::SHIPPING_ADDRESS_SHEET_LIST_VIEW); + } + + // Selects the only shipping address. + void SelectTheOnlyShippingAddress() { + ResetEventWaiterForSequence({DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, + DialogEvent::SPEC_DONE_UPDATING}); + ClickOnChildInListViewAndWait( + /*child_index=*/0, /*total_num_children=*/1, + DialogViewID::SHIPPING_ADDRESS_SHEET_LIST_VIEW); + } + + // Verifies that the first shipping option cost is |amount_string|. + void ExpectShippingCost(const std::string& amount_string) { + EXPECT_EQ(base::ASCIIToUTF16(amount_string), + GetLabelText(DialogViewID::SHIPPING_OPTION_AMOUNT)); + } + + // Clicks the "Pay" button and waits for the dialog to close. + void Pay() { + ResetEventWaiterForSequence( + {DialogEvent::PROCESSING_SPINNER_SHOWN, DialogEvent::DIALOG_CLOSED}); + ClickOnDialogViewAndWait(DialogViewID::PAY_BUTTON, dialog_view()); + } + + private: + DISALLOW_COPY_AND_ASSIGN(PaymentRequestShowPromiseTest); +}; + +IN_PROC_BROWSER_TEST_F(PaymentRequestShowPromiseTest, DigitalGoods) { + NavigateTo("/show_promise/digital_goods.html"); + InstallEchoPaymentHandlerForBasicCard(); + ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "create();")); + ShowBrowserPaymentSheet(); + + EXPECT_TRUE(IsPayButtonEnabled()); + + OpenOrderSummaryScreen(); + + ExpectTotal("$1.00"); + + ClickOnBackArrow(); + Pay(); + + ExpectBodyContains({R"({"currency":"USD","value":"1.00"})"}); +} + +IN_PROC_BROWSER_TEST_F(PaymentRequestShowPromiseTest, SingleOptionShipping) { + NavigateTo("/show_promise/single_option_shipping.html"); + InstallEchoPaymentHandlerForBasicCard(); + AddAutofillProfile(autofill::test::GetFullProfile()); + AddAutofillProfile(autofill::test::GetFullProfile2()); + ShowBrowserPaymentSheet(); + + EXPECT_TRUE(IsPayButtonEnabled()); + + OpenOrderSummaryScreen(); + + ExpectTotal("$1.00"); + + ClickOnBackArrow(); + OpenShippingAddressSectionScreen(); + + ExpectNoShippingWarningMessage(); + + SelectAnotherShippingAddress(); + + ExpectNoShippingWarningMessage(); + + ClickOnBackArrow(); + OpenShippingOptionSectionScreen(); + + ExpectShippingCost("$0.00"); + + ClickOnBackArrow(); + + EXPECT_TRUE(IsPayButtonEnabled()); + + Pay(); + + ExpectBodyContains({R"({"currency":"USD","value":"1.00"})"}); +} + +IN_PROC_BROWSER_TEST_F(PaymentRequestShowPromiseTest, + SingleOptionShippingWithUpdate) { + NavigateTo("/show_promise/single_option_shipping_with_update.html"); + InstallEchoPaymentHandlerForBasicCard(); + AddAutofillProfile(autofill::test::GetFullProfile()); + AddAutofillProfile(autofill::test::GetFullProfile2()); + ShowBrowserPaymentSheet(); + + EXPECT_TRUE(IsPayButtonEnabled()); + + OpenOrderSummaryScreen(); + + ExpectTotal("$1.00"); + + ClickOnBackArrow(); + OpenShippingAddressSectionScreen(); + + ExpectNoShippingWarningMessage(); + + SelectAnotherShippingAddress(); + + ExpectNoShippingWarningMessage(); + + ClickOnBackArrow(); + OpenShippingOptionSectionScreen(); + + ExpectShippingCost("$0.00"); + + ClickOnBackArrow(); + + EXPECT_TRUE(IsPayButtonEnabled()); + + Pay(); + + ExpectBodyContains({R"({"currency":"USD","value":"1.00"})"}); +} + +IN_PROC_BROWSER_TEST_F(PaymentRequestShowPromiseTest, CannotShipError) { + NavigateTo("/show_promise/us_only_shipping.html"); + InstallEchoPaymentHandlerForBasicCard(); + AddAutofillProfile(autofill::test::GetFullCanadianProfile()); + ShowBrowserPaymentSheet(); + + EXPECT_FALSE(IsPayButtonEnabled()); + + OpenOrderSummaryScreen(); + + ExpectTotal("$1.00"); + + ClickOnBackArrow(); + OpenShippingAddressSectionScreen(); + + ExpectShippingWarningMessage( + "To see shipping methods and requirements, select an address"); + + SelectTheOnlyShippingAddress(); + + ExpectShippingWarningMessage("Cannot ship outside of US."); + + ClickOnBackArrow(); + + EXPECT_FALSE(IsPayButtonEnabled()); + + ClickOnCancel(); +} + +#if defined(OS_WIN) || defined(OS_MACOSX) +// Times out flakily on Windows and Mac. +#define CanShipAfterCheckingAddress_MAYBE CanShipAfterCheckingAddress_DISABLED +#else +#define CanShipAfterCheckingAddress_MAYBE CanShipAfterCheckingAddress +#endif +IN_PROC_BROWSER_TEST_F(PaymentRequestShowPromiseTest, + CanShipAfterCheckingAddress_MAYBE) { + NavigateTo("/show_promise/us_only_shipping.html"); + InstallEchoPaymentHandlerForBasicCard(); + AddAutofillProfile(autofill::test::GetFullProfile()); + ShowBrowserPaymentSheet(); + + EXPECT_FALSE(IsPayButtonEnabled()); + + OpenOrderSummaryScreen(); + + ExpectTotal("$1.00"); + + ClickOnBackArrow(); + OpenShippingAddressSectionScreen(); + + ExpectShippingWarningMessage( + "To see shipping methods and requirements, select an address"); + + SelectTheOnlyShippingAddress(); + + EXPECT_TRUE(IsPayButtonEnabled()); + + Pay(); + + ExpectBodyContains({R"({"currency":"USD","value":"1.00"})"}); +} + +IN_PROC_BROWSER_TEST_F(PaymentRequestShowPromiseTest, SkipUI) { + NavigateTo("/show_promise/digital_goods.html"); + InstallEchoPaymentHandlerForBasicCard(); + ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "create();")); + EnalbeSkipUIForForBasicCard(); + ResetEventWaiterForSequence( + {DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, DialogEvent::SPEC_DONE_UPDATING, + DialogEvent::PROCESSING_SPINNER_HIDDEN, DialogEvent::DIALOG_OPENED, + DialogEvent::PROCESSING_SPINNER_SHOWN, DialogEvent::DIALOG_CLOSED}); + ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); + WaitForObservedEvent(); + + ExpectBodyContains({R"({"currency":"USD","value":"1.00"})"}); +} + +IN_PROC_BROWSER_TEST_F(PaymentRequestShowPromiseTest, Reject) { + NavigateTo("/show_promise/reject.html"); + ResetEventWaiterForSequence( + {DialogEvent::PROCESSING_SPINNER_SHOWN, DialogEvent::DIALOG_CLOSED}); + ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); + WaitForObservedEvent(); + + ExpectBodyContains({R"(AbortError)"}); +} + +IN_PROC_BROWSER_TEST_F(PaymentRequestShowPromiseTest, Timeout) { + NavigateTo("/show_promise/timeout.html"); + ResetEventWaiterForSequence( + {DialogEvent::PROCESSING_SPINNER_SHOWN, DialogEvent::DIALOG_CLOSED}); + ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); + WaitForObservedEvent(); + + ExpectBodyContains({R"(AbortError)"}); +} + +IN_PROC_BROWSER_TEST_F(PaymentRequestShowPromiseTest, + UnsupportedPaymentMethod) { + NavigateTo("/show_promise/unsupported.html"); + ResetEventWaiterForSequence( + {DialogEvent::PROCESSING_SPINNER_SHOWN, + DialogEvent::PROCESSING_SPINNER_HIDDEN, DialogEvent::SPEC_DONE_UPDATING, + DialogEvent::PROCESSING_SPINNER_HIDDEN, DialogEvent::NOT_SUPPORTED_ERROR, + DialogEvent::DIALOG_CLOSED}); + ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); + WaitForObservedEvent(); + + ExpectBodyContains( + {R"(NotSupportedError: The payment method "foo" is not supported)"}); +} + +IN_PROC_BROWSER_TEST_F(PaymentRequestShowPromiseTest, InvalidDetails) { + NavigateTo("/show_promise/invalid_details.html"); + ResetEventWaiterForSequence( + {DialogEvent::PROCESSING_SPINNER_SHOWN, DialogEvent::DIALOG_CLOSED}); + ASSERT_TRUE(content::ExecuteScript(GetActiveWebContents(), "buy();")); + WaitForObservedEvent(); + + ExpectBodyContains({R"(Total amount value should be non-negative)"}); +} + +} // namespace +} // namespace payments
diff --git a/chrome/browser/vr/elements/indicator_spec.cc b/chrome/browser/vr/elements/indicator_spec.cc index f44e73f..80c5251 100644 --- a/chrome/browser/vr/elements/indicator_spec.cc +++ b/chrome/browser/vr/elements/indicator_spec.cc
@@ -3,6 +3,7 @@ // found in the LICENSE file. #include "chrome/browser/vr/elements/indicator_spec.h" +#include "build/build_config.h" #include "chrome/browser/vr/ui_support.h" #include "chrome/grit/generated_resources.h" @@ -80,7 +81,26 @@ IDS_VR_SHELL_BG_IS_SHARING_SCREEN, IDS_VR_SHELL_SITE_CAN_SHARE_SCREEN, &CapturingStateModel::screen_capture_enabled, - false}}; + false}, + +#if !defined(OS_ANDROID) + {kUsbConnectedIndicator, kWebXrUsbConnectedIndicator, + GetVrIcon(kVrUsbIcon), + IDS_VR_SHELL_SITE_IS_USING_USB, + 0, + 0, + &CapturingStateModel::usb_connected, + false}, + + {kMidiConnectedIndicator, kWebXrMidiConnectedIndicator, + GetVrIcon(kVrMidiIcon), + IDS_VR_SHELL_SITE_IS_USING_MIDI, + 0, + IDS_VR_SHELL_SITE_CAN_USE_MIDI, + &CapturingStateModel::midi_connected, + false}, +#endif + }; return specs; }
diff --git a/chrome/browser/vr/elements/ui_element_name.cc b/chrome/browser/vr/elements/ui_element_name.cc index cdc4cb6..b8d1a0c 100644 --- a/chrome/browser/vr/elements/ui_element_name.cc +++ b/chrome/browser/vr/elements/ui_element_name.cc
@@ -148,6 +148,10 @@ "kContentRepositionHitPlane", "kContentRepositionVisibilityToggle", "kWebXrExternalPromptNotification", + "kUsbConnectedIndicator", + "kWebXrUsbConnectedIndicator", + "kMidiConnectedIndicator", + "kWebXrMidiConnectedIndicator", }; static_assert(
diff --git a/chrome/browser/vr/elements/ui_element_name.h b/chrome/browser/vr/elements/ui_element_name.h index 42feb49..0ab4061b 100644 --- a/chrome/browser/vr/elements/ui_element_name.h +++ b/chrome/browser/vr/elements/ui_element_name.h
@@ -149,6 +149,10 @@ kContentRepositionHitPlane, kContentRepositionVisibilityToggle, kWebXrExternalPromptNotification, + kUsbConnectedIndicator, + kWebXrUsbConnectedIndicator, + kMidiConnectedIndicator, + kWebXrMidiConnectedIndicator, // This must be last. kNumUiElementNames,
diff --git a/chrome/browser/vr/model/capturing_state_model.h b/chrome/browser/vr/model/capturing_state_model.h index 6e5f0d25..d1a8e927 100644 --- a/chrome/browser/vr/model/capturing_state_model.h +++ b/chrome/browser/vr/model/capturing_state_model.h
@@ -17,23 +17,27 @@ bool screen_capture_enabled = false; bool location_access_enabled = false; bool bluetooth_connected = false; + bool usb_connected = false; + bool midi_connected = false; bool operator==(const CapturingStateModel& rhs) const { return audio_capture_enabled == rhs.audio_capture_enabled && video_capture_enabled == rhs.video_capture_enabled && screen_capture_enabled == rhs.screen_capture_enabled && location_access_enabled == rhs.location_access_enabled && - bluetooth_connected == rhs.bluetooth_connected; + bluetooth_connected == rhs.bluetooth_connected && + usb_connected == rhs.usb_connected && + midi_connected == rhs.midi_connected; } bool operator!=(const CapturingStateModel& rhs) const { return !(*this == rhs); } - bool IsAnyCapturingEnabled() const { + bool IsAtleastOnePermissionGrantedOrInUse() const { return audio_capture_enabled || video_capture_enabled || screen_capture_enabled || location_access_enabled || - bluetooth_connected; + bluetooth_connected || usb_connected || midi_connected; } };
diff --git a/chrome/browser/vr/ui_scene_creator.cc b/chrome/browser/vr/ui_scene_creator.cc index fd69a8b..755818c 100644 --- a/chrome/browser/vr/ui_scene_creator.cc +++ b/chrome/browser/vr/ui_scene_creator.cc
@@ -968,7 +968,7 @@ // upfront (struct potential_capture). Then, when a device gets accessed, // an indicator notifies the user about its usage. // The below logic tries to capture this logic. - bool initial_toasts = !active_capture.IsAnyCapturingEnabled(); + bool initial_toasts = !active_capture.IsAtleastOnePermissionGrantedOrInUse(); if (active_capture != last_active_capture || potential_capture != last_potential_capture) { auto specs = GetIndicatorSpecs();
diff --git a/chrome/browser/vr/ui_support.cc b/chrome/browser/vr/ui_support.cc index 47e15234..35f55a55 100644 --- a/chrome/browser/vr/ui_support.cc +++ b/chrome/browser/vr/ui_support.cc
@@ -66,6 +66,10 @@ #if !defined(OS_ANDROID) case kVrOpenInBrowserIcon: return kOpenInBrowserIcon; + case kVrUsbIcon: + return vector_icons::kUsbIcon; + case kVrMidiIcon: + return vector_icons::kMidiIcon; #endif default: NOTREACHED();
diff --git a/chrome/browser/vr/ui_support.h b/chrome/browser/vr/ui_support.h index 97c6374..41803681 100644 --- a/chrome/browser/vr/ui_support.h +++ b/chrome/browser/vr/ui_support.h
@@ -45,6 +45,8 @@ kVrDaydreamControllerAppButtonIcon, kVrDaydreamControllerHomeButtonIcon, kVrOpenInBrowserIcon, + kVrUsbIcon, + kVrMidiIcon, }; VR_BASE_EXPORT const gfx::VectorIcon& GetVrIcon(VrIconId icon);
diff --git a/chrome/browser/vr/ui_unittest.cc b/chrome/browser/vr/ui_unittest.cc index 070be975..86688f1c 100644 --- a/chrome/browser/vr/ui_unittest.cc +++ b/chrome/browser/vr/ui_unittest.cc
@@ -181,6 +181,10 @@ for (auto& spec : GetIndicatorSpecs()) { for (int i = 0; i < 3; ++i) { +#if defined(OS_WIN) + if (i == 1) // Windows doesn't look at background capturing. Skip. + continue; +#endif browser_ui->SetWebVrMode(true); ui_->GetSchedulerUiPtr()->OnWebXrFrameAvailable(); @@ -189,14 +193,34 @@ CapturingStateModel potential_capturing; active_capturing.*spec.signal = i == 0; // High accuracy location cannot be used in a background tab. + // Also, capturing USB and Midi cannot be done in background tab. background_capturing.*spec.signal = - i == 1 && spec.name != kLocationAccessIndicator; - potential_capturing.*spec.signal = true; + i == 1 && spec.name != kLocationAccessIndicator && + spec.name != kUsbConnectedIndicator && + spec.name != kMidiConnectedIndicator; + potential_capturing.*spec.signal = + i == 2 && spec.name != kUsbConnectedIndicator; + + int string_id = 0; + switch (i) { + case 0: + string_id = spec.resource_string; + break; + case 1: + string_id = spec.background_resource_string; + break; + case 2: + string_id = spec.potential_resource_string; + break; + default: + NOTREACHED(); + break; + } browser_ui->SetCapturingState(active_capturing, background_capturing, potential_capturing); EXPECT_TRUE(IsVisible(kWebVrExclusiveScreenToast)); - EXPECT_TRUE(IsVisible(spec.webvr_name)); + EXPECT_TRUE(IsVisible(spec.webvr_name) == (string_id != 0)); EXPECT_TRUE(RunForSeconds(kToastTimeoutSeconds + kSmallDelaySeconds)); EXPECT_FALSE(IsVisible(kWebVrExclusiveScreenToast)); @@ -624,6 +648,8 @@ model_->active_capturing.screen_capture_enabled = true; model_->active_capturing.location_access_enabled = true; model_->active_capturing.bluetooth_connected = true; + model_->active_capturing.usb_connected = true; + model_->active_capturing.midi_connected = true; VerifyOnlyElementsVisible("Elements hidden", std::set<UiElementName>{kWebVrBackground}); @@ -653,6 +679,8 @@ model_->active_capturing.screen_capture_enabled = true; model_->active_capturing.location_access_enabled = true; model_->active_capturing.bluetooth_connected = true; + model_->active_capturing.usb_connected = true; + model_->active_capturing.midi_connected = true; // Transition to WebVR mode ui_->GetBrowserUiWeakPtr()->SetWebVrMode(true); @@ -680,6 +708,8 @@ model_->active_capturing.screen_capture_enabled = true; model_->active_capturing.location_access_enabled = true; model_->active_capturing.bluetooth_connected = true; + model_->active_capturing.usb_connected = true; + model_->active_capturing.midi_connected = true; EXPECT_TRUE(VerifyVisibility(indicators, true)); EXPECT_TRUE(VerifyRequiresLayout(indicators, true)); @@ -701,6 +731,8 @@ model_->active_capturing.screen_capture_enabled = false; model_->active_capturing.location_access_enabled = false; model_->active_capturing.bluetooth_connected = false; + model_->active_capturing.usb_connected = false; + model_->active_capturing.midi_connected = false; EXPECT_TRUE(VerifyRequiresLayout(indicators, false)); }
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 5b9dee98..13e679e 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -1681,6 +1681,7 @@ "../browser/ui/views/payments/payment_request_payment_app_browsertest.cc", "../browser/ui/views/payments/payment_request_payment_response_browsertest.cc", "../browser/ui/views/payments/payment_request_shipping_address_instance_browsertest.cc", + "../browser/ui/views/payments/payment_request_show_promise_browsertest.cc", "../browser/ui/views/payments/payment_request_update_with_browsertest.cc", "../browser/ui/views/payments/payment_request_use_stats_browsertest.cc", "../browser/ui/views/payments/payment_sheet_view_controller_browsertest.cc", @@ -2421,9 +2422,12 @@ ] data = [ - "//testing:run_perf_test", "//tools/perf/contrib/cluster_telemetry/", ] + + data_deps = [ + "//testing:run_perf_test", + ] } # New target that will replace telemetry_perf_tests when testing
diff --git a/chrome/test/data/webui/print_preview/system_dialog_browsertest.js b/chrome/test/data/webui/print_preview/system_dialog_browsertest.js index 7adbad5..ff6774a 100644 --- a/chrome/test/data/webui/print_preview/system_dialog_browsertest.js +++ b/chrome/test/data/webui/print_preview/system_dialog_browsertest.js
@@ -45,14 +45,15 @@ const previewArea = page.$.previewArea; pluginProxy.setLoadCallback(previewArea.onPluginLoad_.bind(previewArea)); sidebar = page.$$('print-preview-sidebar'); - linkContainer = sidebar.$$('print-preview-link-container'); return Promise .all([ + test_util.waitForRender(page), print_preview.Model.whenReady(), nativeLayer.whenCalled('getInitialSettings'), nativeLayer.whenCalled('getPrinterCapabilities'), ]) .then(function() { + linkContainer = sidebar.$$('print-preview-link-container'); return nativeLayer.whenCalled('getPreview'); }) .then(function() {
diff --git a/chrome/test/data/webui/welcome/nux_ntp_background_test.js b/chrome/test/data/webui/welcome/nux_ntp_background_test.js index b8835944..0dd420fe 100644 --- a/chrome/test/data/webui/welcome/nux_ntp_background_test.js +++ b/chrome/test/data/webui/welcome/nux_ntp_background_test.js
@@ -58,25 +58,22 @@ }); test('test displaying default and custom background', function() { - const options = testElement.shadowRoot.querySelectorAll( - '.ntp-background-grid-button'); + const options = testElement.shadowRoot.querySelectorAll('.option'); assertEquals(3, options.length); // the first option should be the 'Default' option assertEquals( - options[0].querySelector('.ntp-background-title').innerText, - 'Default'); + options[0].querySelector('.option-name').innerText, 'Default'); for (let i = 0; i < backgrounds.length; i++) { assertEquals( - options[i + 1].querySelector('.ntp-background-title').innerText, + options[i + 1].querySelector('.option-name').innerText, backgrounds[i].title); } }); test('test previewing a background and going back to default', function() { - const options = testElement.shadowRoot.querySelectorAll( - '.ntp-background-grid-button'); + const options = testElement.shadowRoot.querySelectorAll('.option'); options[1].click(); return testNtpBackgroundProxy.whenCalled('preloadImage').then(() => { @@ -98,8 +95,7 @@ }); test('test activating a background', function() { - const options = testElement.shadowRoot.querySelectorAll( - '.ntp-background-grid-button'); + const options = testElement.shadowRoot.querySelectorAll('.option'); options[1].click(); assertFalse(options[0].hasAttribute('active')); @@ -109,8 +105,7 @@ test('test setting the background when hitting next', function() { // select the first non-default option and hit 'Next' - const options = testElement.shadowRoot.querySelectorAll( - '.ntp-background-grid-button'); + const options = testElement.shadowRoot.querySelectorAll('.option'); options[1].click(); testElement.$$('.action-button').click(); return Promise @@ -124,8 +119,7 @@ }); test('test metrics for selecting an option and skipping', function() { - const options = testElement.shadowRoot.querySelectorAll( - '.ntp-background-grid-button'); + const options = testElement.shadowRoot.querySelectorAll('.option'); options[1].click(); testElement.$.skipButton.click(); return testMetricsProxy.whenCalled('recordChoseAnOptionAndChoseSkip'); @@ -135,8 +129,7 @@ 'test metrics for when there is an error previewing the background', function() { testNtpBackgroundProxy.setPreloadImageSuccess(false); - const options = testElement.shadowRoot.querySelectorAll( - '.ntp-background-grid-button'); + const options = testElement.shadowRoot.querySelectorAll('.option'); options[1].click(); return testNtpBackgroundProxy.whenCalled( 'recordBackgroundImageFailedToLoad'); @@ -146,8 +139,7 @@ `test metrics aren't sent when previewing the background is a success`, function() { testNtpBackgroundProxy.setPreloadImageSuccess(true); - const options = testElement.shadowRoot.querySelectorAll( - '.ntp-background-grid-button'); + const options = testElement.shadowRoot.querySelectorAll('.option'); options[1].click(); return testNtpBackgroundProxy.whenCalled('preloadImage').then(() => { assertEquals( @@ -159,8 +151,7 @@ test('test metrics for load times of background images', function() { testNtpBackgroundProxy.setPreloadImageSuccess(true); - const options = testElement.shadowRoot.querySelectorAll( - '.ntp-background-grid-button'); + const options = testElement.shadowRoot.querySelectorAll('.option'); options[1].click(); return testNtpBackgroundProxy.whenCalled('recordBackgroundImageLoadTime'); }); @@ -177,8 +168,7 @@ test('test clearing the background when default is selected', function() { // select the default option and hit 'Next' - const options = testElement.shadowRoot.querySelectorAll( - '.ntp-background-grid-button'); + const options = testElement.shadowRoot.querySelectorAll('.option'); options[0].click(); testElement.$$('.action-button').click(); return testNtpBackgroundProxy.whenCalled('clearBackground');
diff --git a/chrome/tools/build/mac/copy_keystone_framework.py b/chrome/tools/build/mac/copy_keystone_framework.py index 513fdc91..7d34575a 100644 --- a/chrome/tools/build/mac/copy_keystone_framework.py +++ b/chrome/tools/build/mac/copy_keystone_framework.py
@@ -36,10 +36,6 @@ os.path.join(args[1], 'Versions/Current/'), output_path]) - # Thin the library to just the required arch. - library_path = os.path.join(output_path, 'KeystoneRegistration') - subprocess.check_call( - ['lipo', '-thin', 'x86_64', library_path, '-o', library_path]) return 0
diff --git a/components/bookmarks/browser/bookmark_storage.cc b/components/bookmarks/browser/bookmark_storage.cc index 4131094..7299cef 100644 --- a/components/bookmarks/browser/bookmark_storage.cc +++ b/components/bookmarks/browser/bookmark_storage.cc
@@ -6,6 +6,7 @@ #include <stddef.h> #include <algorithm> +#include <unordered_map> #include <utility> #include "base/bind.h" @@ -14,6 +15,7 @@ #include "base/json/json_file_value_serializer.h" #include "base/json/json_reader.h" #include "base/json/json_string_value_serializer.h" +#include "base/metrics/histogram_functions.h" #include "base/metrics/histogram_macros.h" #include "base/numerics/safe_conversions.h" #include "base/sequenced_task_runner.h" @@ -56,9 +58,61 @@ } } +// Helper function to recursively traverse the bookmark tree and count the +// number of bookmarks (excluding folders) per URL (more precisely, per URL +// hash). +void PopulateNumNodesPerUrlHash( + const BookmarkNode* node, + std::unordered_map<size_t, int>* num_nodes_per_url_hash) { + DCHECK(num_nodes_per_url_hash); + DCHECK(node); + + if (!node->is_folder()) + (*num_nodes_per_url_hash)[std::hash<std::string>()(node->url().spec())]++; + + for (int i = 0; i < node->child_count(); ++i) + PopulateNumNodesPerUrlHash(node->GetChild(i), num_nodes_per_url_hash); +} + +// Computes the number of bookmarks (excluding folders) with a URL that is used +// by at least one other bookmark. +int GetNumDuplicateUrls(const BookmarkNode* root) { + DCHECK(root); + + // The key is hash of the URL, instead of the full URL, to keep memory usage + // low. The value indicates the node count. + std::unordered_map<size_t, int> num_nodes_per_url_hash; + PopulateNumNodesPerUrlHash(root, &num_nodes_per_url_hash); + + int num_duplicate_urls = 0; + for (const auto& url_hash_and_count : num_nodes_per_url_hash) { + if (url_hash_and_count.second > 1) + num_duplicate_urls += url_hash_and_count.second; + } + return num_duplicate_urls; +} + +// Computes the number of bookmarks with an empty title. This includes folders +// too except for the root. +int GetNumNodesWithEmptyTitle(const BookmarkNode* node) { + DCHECK(node); + + int num_nodes_with_empty_title = 0; + + if (!node->is_root() && node->GetTitle().empty()) + ++num_nodes_with_empty_title; + + for (int i = 0; i < node->child_count(); ++i) + num_nodes_with_empty_title += GetNumNodesWithEmptyTitle(node->GetChild(i)); + + return num_nodes_with_empty_title; +} + } // namespace -void LoadBookmarks(const base::FilePath& path, BookmarkLoadDetails* details) { +void LoadBookmarks(const base::FilePath& path, + bool emit_experimental_uma, + BookmarkLoadDetails* details) { bool load_index = false; bool bookmark_file_exists = base::PathExists(path); if (bookmark_file_exists) { @@ -120,6 +174,26 @@ UMA_HISTOGRAM_COUNTS_100000( "Bookmarks.Count.OnProfileLoad", base::saturated_cast<int>(details->url_index()->UrlCount())); + + if (emit_experimental_uma && details->root_node()) { + TimeTicks start_time = TimeTicks::Now(); + + int num_duplicate_urls = GetNumDuplicateUrls(details->root_node()); + if (num_duplicate_urls > 0) { + base::UmaHistogramCounts10000( + "Bookmarks.Count.OnProfileLoad.DuplicateUrl", num_duplicate_urls); + } + + int num_nodes_with_empty_title = + GetNumNodesWithEmptyTitle(details->root_node()); + if (num_nodes_with_empty_title > 0) { + base::UmaHistogramCounts10000("Bookmarks.Count.OnProfileLoad.EmptyTitle", + num_nodes_with_empty_title); + } + + UMA_HISTOGRAM_TIMES("Bookmarks.DuplicateAndEmptyTitleDetectionTime", + TimeTicks::Now() - start_time); + } } // BookmarkLoadDetails ---------------------------------------------------------
diff --git a/components/bookmarks/browser/bookmark_storage.h b/components/bookmarks/browser/bookmark_storage.h index 1abc6da..c611e5f 100644 --- a/components/bookmarks/browser/bookmark_storage.h +++ b/components/bookmarks/browser/bookmark_storage.h
@@ -141,8 +141,11 @@ }; // Loads the bookmarks. This is intended to be called on the background thread. -// Updates state in |details| based on the load. +// Updates state in |details| based on the load. |emit_experimental_uma| +// determines whether a few newly introduced and experimental UMA metrics should +// be logged. void LoadBookmarks(const base::FilePath& profile_path, + bool emit_experimental_uma, BookmarkLoadDetails* details); // BookmarkStorage handles reading/write the bookmark bar model. The
diff --git a/components/bookmarks/browser/model_loader.cc b/components/bookmarks/browser/model_loader.cc index f1316cd..12fe8d32 100644 --- a/components/bookmarks/browser/model_loader.cc +++ b/components/bookmarks/browser/model_loader.cc
@@ -5,6 +5,7 @@ #include "components/bookmarks/browser/model_loader.h" #include "base/bind.h" +#include "base/feature_list.h" #include "base/files/file_path.h" #include "base/threading/thread_task_runner_handle.h" #include "components/bookmarks/browser/bookmark_storage.h" @@ -12,6 +13,15 @@ namespace bookmarks { +namespace { + +// TODO(mastiz): Remove this kill switch asap since the UMA metrics entail +// negligible risks for stability or performance overhead. +const base::Feature kEmitExperimentalBookmarkLoadUma{ + "EmitExperimentalBookmarkLoadUma", base::FEATURE_ENABLED_BY_DEFAULT}; + +} // namespace + // static scoped_refptr<ModelLoader> ModelLoader::Create( const base::FilePath& profile_path, @@ -21,11 +31,18 @@ // Note: base::MakeRefCounted is not available here, as ModelLoader's // constructor is private. auto model_loader = base::WrapRefCounted(new ModelLoader()); + // We plumb the value for kEmitExperimentalBookmarkLoadUma as retrieved on + // the UI thread to avoid issues with TSAN bots (in case there are tests that + // override feature toggles -not necessarily this one- while bookmark loading + // is ongoing, which is problematic due to how feature overriding for tests is + // implemented). load_sequenced_task_runner->PostTask( FROM_HERE, - base::BindOnce(&ModelLoader::DoLoadOnBackgroundThread, model_loader, - profile_path, base::ThreadTaskRunnerHandle::Get(), - std::move(details), std::move(callback))); + base::BindOnce( + &ModelLoader::DoLoadOnBackgroundThread, model_loader, profile_path, + base::FeatureList::IsEnabled(kEmitExperimentalBookmarkLoadUma), + base::ThreadTaskRunnerHandle::Get(), std::move(details), + std::move(callback))); return model_loader; } @@ -41,10 +58,11 @@ void ModelLoader::DoLoadOnBackgroundThread( const base::FilePath& profile_path, + bool emit_experimental_uma, scoped_refptr<base::SequencedTaskRunner> main_sequenced_task_runner, std::unique_ptr<BookmarkLoadDetails> details, LoadCallback callback) { - LoadBookmarks(profile_path, details.get()); + LoadBookmarks(profile_path, emit_experimental_uma, details.get()); history_bookmark_model_ = details->url_index(); loaded_signal_.Signal(); main_sequenced_task_runner->PostTask(
diff --git a/components/bookmarks/browser/model_loader.h b/components/bookmarks/browser/model_loader.h index 1a1477cb..6ff48d1d 100644 --- a/components/bookmarks/browser/model_loader.h +++ b/components/bookmarks/browser/model_loader.h
@@ -57,6 +57,7 @@ // Performs the load on a background thread. void DoLoadOnBackgroundThread( const base::FilePath& profile_path, + bool emit_experimental_uma, scoped_refptr<base::SequencedTaskRunner> main_sequenced_task_runner, std::unique_ptr<BookmarkLoadDetails> details, LoadCallback callback);
diff --git a/components/payments/content/payment_request.cc b/components/payments/content/payment_request.cc index 3ae1a62..b37be61a 100644 --- a/components/payments/content/payment_request.cc +++ b/components/payments/content/payment_request.cc
@@ -164,7 +164,7 @@ spec_->url_payment_method_identifiers().end()); } -void PaymentRequest::Show(bool is_user_gesture) { +void PaymentRequest::Show(bool is_user_gesture, bool wait_for_updated_details) { if (!IsInitialized()) { log_.Error("Attempted show without initialization"); OnConnectionTerminated(); @@ -207,8 +207,14 @@ is_show_user_gesture_ = is_user_gesture; - display_handle_->Show(this); + if (wait_for_updated_details) { + // Put |spec_| into uninitialized state, so the UI knows to show a spinner. + // This method does not block. + spec_->StartWaitingForUpdateWith( + PaymentRequestSpec::UpdateReason::INITIAL_PAYMENT_DETAILS); + } + display_handle_->Show(this); state_->AreRequestedMethodsSupported( base::BindOnce(&PaymentRequest::AreRequestedMethodsSupportedCallback, weak_ptr_factory_.GetWeakPtr())); @@ -253,6 +259,13 @@ return; } + bool is_resolving_promise_passed_into_show_method = !spec_->IsInitialized(); + if (is_resolving_promise_passed_into_show_method && !details->total) { + log_.Error("Missing total"); + OnConnectionTerminated(); + return; + } + std::string error; if (!ValidatePaymentDetails(ConvertPaymentDetails(details), &error)) { log_.Error(error); @@ -269,6 +282,15 @@ } spec_->UpdateWith(std::move(details)); + + if (is_resolving_promise_passed_into_show_method) { + if (SatisfiesSkipUIConstraints()) { + skipped_payment_request_ui_ = true; + Pay(); + } else if (spec_->request_shipping()) { + state_->SelectDefaultShippingAddressAndNotifyObservers(); + } + } } void PaymentRequest::NoUpdatedPaymentDetails() { @@ -425,16 +447,17 @@ } bool PaymentRequest::SatisfiesSkipUIConstraints() const { - return base::FeatureList::IsEnabled(features::kWebPaymentsSingleAppUiSkip) && + // Only allowing URL base payment apps to skip the payment sheet. + return (spec()->url_payment_method_identifiers().size() == 1 || + skip_ui_for_non_url_payment_method_identifiers_for_test_) && + base::FeatureList::IsEnabled(features::kWebPaymentsSingleAppUiSkip) && base::FeatureList::IsEnabled(::features::kServiceWorkerPaymentApps) && - is_show_user_gesture_ && state()->is_get_all_instruments_finished() && + is_show_user_gesture_ && state()->IsInitialized() && + spec()->IsInitialized() && state()->available_instruments().size() == 1 && spec()->stringified_method_data().size() == 1 && !spec()->request_shipping() && !spec()->request_payer_name() && - !spec()->request_payer_phone() && - !spec()->request_payer_email() - // Only allowing URL base payment apps to skip the payment sheet. - && spec()->url_payment_method_identifiers().size() == 1; + !spec()->request_payer_phone() && !spec()->request_payer_email(); } void PaymentRequest::OnPaymentResponseAvailable(
diff --git a/components/payments/content/payment_request.h b/components/payments/content/payment_request.h index ef4236b..4394b82 100644 --- a/components/payments/content/payment_request.h +++ b/components/payments/content/payment_request.h
@@ -68,7 +68,7 @@ std::vector<mojom::PaymentMethodDataPtr> method_data, mojom::PaymentDetailsPtr details, mojom::PaymentOptionsPtr options) override; - void Show(bool is_user_gesture) override; + void Show(bool is_user_gesture, bool wait_for_updated_details) override; void Retry(mojom::PaymentValidationErrorsPtr errors) override; void UpdateWith(mojom::PaymentDetailsPtr details) override; void NoUpdatedPaymentDetails() override; @@ -122,6 +122,12 @@ PaymentRequestSpec* spec() const { return spec_.get(); } PaymentRequestState* state() const { return state_.get(); } + // Allow to skip UI into payment handlers for such payment methods as + // "basic-card". Used only in tests. + void set_skip_ui_for_non_url_payment_method_identifiers_for_test() { + skip_ui_for_non_url_payment_method_identifiers_for_test_ = true; + } + private: // Returns true after init() has been called and the mojo connection has been // established. If the mojo connection gets later disconnected, this will @@ -205,6 +211,11 @@ // Whether PaymentRequest.show() has been called. bool is_show_called_ = false; + // Whether payment instruments for such payment methods as "basic-card" can + // skip UI for testing of the skip-UI flow. This is always false in + // production. + bool skip_ui_for_non_url_payment_method_identifiers_for_test_ = false; + base::WeakPtrFactory<PaymentRequest> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(PaymentRequest);
diff --git a/components/payments/content/payment_request_spec.cc b/components/payments/content/payment_request_spec.cc index 00e8ff7..3c083ba 100644 --- a/components/payments/content/payment_request_spec.cc +++ b/components/payments/content/payment_request_spec.cc
@@ -100,6 +100,7 @@ void PaymentRequestSpec::UpdateWith(mojom::PaymentDetailsPtr details) { DCHECK(details_); + DCHECK(details_->total || details->total); if (details->total) details_->total = std::move(details->total); if (!details->display_items.empty()) @@ -214,9 +215,15 @@ void PaymentRequestSpec::RecomputeSpecForDetails() { // Reparse the |details_| and update the observers. - UpdateSelectedShippingOption(/*after_update=*/true); + bool is_initialization = + current_update_reason_ == UpdateReason::INITIAL_PAYMENT_DETAILS; + UpdateSelectedShippingOption(/*after_update=*/!is_initialization); NotifyOnSpecUpdated(); + + if (is_initialization) + NotifyInitialized(); + current_update_reason_ = UpdateReason::NONE; } @@ -229,6 +236,10 @@ observers_.RemoveObserver(observer); } +bool PaymentRequestSpec::IsInitialized() const { + return current_update_reason_ != UpdateReason::INITIAL_PAYMENT_DETAILS; +} + bool PaymentRequestSpec::request_shipping() const { return options_->request_shipping; } @@ -365,7 +376,7 @@ selected_shipping_option_ = nullptr; selected_shipping_option_error_.clear(); if (details_->shipping_options->empty() || !details_->error.empty()) { - // No options are provided by the merchant. + // The merchant provided either no shipping options or an error message. if (after_update) { // This is after an update, which means that the selected address is not // supported. The merchant may have customized the error string, or a
diff --git a/components/payments/content/payment_request_spec.h b/components/payments/content/payment_request_spec.h index 1ebea6c..a81d0ce 100644 --- a/components/payments/content/payment_request_spec.h +++ b/components/payments/content/payment_request_spec.h
@@ -15,6 +15,7 @@ #include "base/strings/string16.h" #include "components/autofill/core/browser/credit_card.h" #include "components/autofill/core/browser/field_types.h" +#include "components/payments/content/initialization_task.h" #include "components/payments/core/currency_formatter.h" #include "components/payments/core/payment_options_provider.h" #include "third_party/blink/public/mojom/payments/payment_request.mojom.h" @@ -33,12 +34,22 @@ // The spec contains all the options that the merchant has specified about this // Payment Request. It's a (mostly) read-only view, which can be updated in // certain occasions by the merchant (see API). -class PaymentRequestSpec : public PaymentOptionsProvider { +// +// The spec starts out completely initialized when a PaymentRequest object is +// created, but can be placed into uninitialized state if PaymentRequest.show() +// was called with a promise. This allows for asynchronous calculation of the +// shopping cart contents, the total, the shipping options, and the modifiers. +// +// The initialization state is observed by PaymentRequestDialogView for showing +// a "Loading..." spinner. +class PaymentRequestSpec : public PaymentOptionsProvider, + public InitializationTask { public: // This enum represents which bit of information was changed to trigger an // update roundtrip with the website. enum class UpdateReason { NONE, + INITIAL_PAYMENT_DETAILS, SHIPPING_OPTION, SHIPPING_ADDRESS, RETRY, @@ -104,6 +115,9 @@ void AddObserver(Observer* observer); void RemoveObserver(Observer* observer); + // InitializationTask: + bool IsInitialized() const override; + // PaymentOptionsProvider: bool request_shipping() const override; bool request_payer_name() const override; @@ -158,7 +172,11 @@ return selected_shipping_option_error_; } + // Notifies observers that spec is going to be updated due to |reason|. This + // shows a spinner in UI that goes away when merchant calls updateWith() or + // ignores the shipping*change event. void StartWaitingForUpdateWith(UpdateReason reason); + bool IsMixedCurrency() const; UpdateReason current_update_reason() const { return current_update_reason_; } @@ -188,8 +206,9 @@ // Updates the |selected_shipping_option| based on the data passed to this // payment request by the website. This will set selected_shipping_option_ to - // the last option marked selected in the options array. If no options are - // provided and this method is called |after_update|, it means the merchant + // the last option marked selected in the options array. If merchants provides + // no options or an error message this method is called |after_update| (after + // user changed their shipping address selection), it means the merchant // doesn't ship to this location. In this case, // |selected_shipping_option_error_| will be set. void UpdateSelectedShippingOption(bool after_update);
diff --git a/components/payments/content/payment_request_spec_unittest.cc b/components/payments/content/payment_request_spec_unittest.cc index 609e7d2..58a9dd1 100644 --- a/components/payments/content/payment_request_spec_unittest.cc +++ b/components/payments/content/payment_request_spec_unittest.cc
@@ -32,6 +32,8 @@ void RecreateSpecWithOptionsAndDetails(mojom::PaymentOptionsPtr options, mojom::PaymentDetailsPtr details) { + if (!details->total) + details->total = mojom::PaymentItem::New(); spec_ = std::make_unique<PaymentRequestSpec>( std::move(options), std::move(details), std::vector<mojom::PaymentMethodDataPtr>(), this, "en-US");
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc index c86818e9..93a39e0 100644 --- a/components/payments/content/payment_request_state.cc +++ b/components/payments/content/payment_request_state.cc
@@ -147,6 +147,7 @@ get_all_instruments_finished_ = true; are_requested_methods_supported_ |= !available_instruments_.empty(); NotifyOnGetAllPaymentInstrumentsFinished(); + NotifyInitialized(); // Fulfill the pending CanMakePayment call. if (can_make_payment_callback_) { @@ -457,6 +458,18 @@ return get_all_instruments_finished_; } +void PaymentRequestState::SelectDefaultShippingAddressAndNotifyObservers() { + // Only pre-select an address if the merchant provided at least one selected + // shipping option, and the top profile is complete. Assumes that profiles + // have already been sorted for completeness and frecency. + if (!shipping_profiles().empty() && spec_->selected_shipping_option() && + profile_comparator()->IsShippingComplete(shipping_profiles_[0])) { + selected_shipping_profile_ = shipping_profiles()[0]; + } + + UpdateIsReadyToPayAndNotifyObservers(); +} + void PaymentRequestState::PopulateProfileCache() { std::vector<autofill::AutofillProfile*> profiles = personal_data_manager_->GetProfilesToSuggest(); @@ -511,14 +524,6 @@ } void PaymentRequestState::SetDefaultProfileSelections() { - // Only pre-select an address if the merchant provided at least one selected - // shipping option, and the top profile is complete. Assumes that profiles - // have already been sorted for completeness and frecency. - if (!shipping_profiles().empty() && spec_->selected_shipping_option() && - profile_comparator()->IsShippingComplete(shipping_profiles_[0])) { - selected_shipping_profile_ = shipping_profiles()[0]; - } - // Contact profiles were ordered by completeness in addition to frecency; // the first one is the best default selection. if (!contact_profiles().empty() && @@ -539,7 +544,8 @@ selected_instrument_ = first_complete_instrument == instruments.end() ? nullptr : first_complete_instrument->get(); - UpdateIsReadyToPayAndNotifyObservers(); + + SelectDefaultShippingAddressAndNotifyObservers(); bool has_complete_instrument = available_instruments().empty() @@ -560,7 +566,6 @@ void PaymentRequestState::NotifyOnGetAllPaymentInstrumentsFinished() { for (auto& observer : observers_) observer.OnGetAllPaymentInstrumentsFinished(); - NotifyInitialized(); } void PaymentRequestState::NotifyOnSelectedInformationChanged() {
diff --git a/components/payments/content/payment_request_state.h b/components/payments/content/payment_request_state.h index cc9dadfb..60c83e81 100644 --- a/components/payments/content/payment_request_state.h +++ b/components/payments/content/payment_request_state.h
@@ -39,6 +39,9 @@ // user is ready to pay. Uses information from the PaymentRequestSpec, which is // what the merchant has specified, as input into the "is ready to pay" // computation. +// +// The initialization state is observed by PaymentRequestDialogView for showing +// a "Loading..." spinner. class PaymentRequestState : public PaymentResponseHelper::Delegate, public PaymentRequestSpec::Observer, public InitializationTask { @@ -224,6 +227,9 @@ // InitializationTask: bool IsInitialized() const override; + // Selects the default shipping address. + void SelectDefaultShippingAddressAndNotifyObservers(); + private: // Fetches the Autofill Profiles for this user from the PersonalDataManager, // and stores copies of them, owned by this PaymentRequestState, in
diff --git a/components/payments/content/payment_request_state_unittest.cc b/components/payments/content/payment_request_state_unittest.cc index e53508b..99c24be 100644 --- a/components/payments/content/payment_request_state_unittest.cc +++ b/components/payments/content/payment_request_state_unittest.cc
@@ -68,6 +68,8 @@ mojom::PaymentOptionsPtr options, mojom::PaymentDetailsPtr details, std::vector<mojom::PaymentMethodDataPtr> method_data) { + if (!details->total) + details->total = mojom::PaymentItem::New(); // The spec will be based on the |options| and |details| passed in. spec_ = std::make_unique<PaymentRequestSpec>( std::move(options), std::move(details), std::move(method_data),
diff --git a/components/test/data/payments/show_promise/app.js b/components/test/data/payments/show_promise/app.js new file mode 100644 index 0000000..cec6d41 --- /dev/null +++ b/components/test/data/payments/show_promise/app.js
@@ -0,0 +1,9 @@ +/* + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +self.addEventListener('paymentrequest', (evt) => { + evt.respondWith({methodName: 'basic-card', details: evt.total}); +});
diff --git a/components/test/data/payments/show_promise/app_installer.js b/components/test/data/payments/show_promise/app_installer.js new file mode 100644 index 0000000..ae296caf --- /dev/null +++ b/components/test/data/payments/show_promise/app_installer.js
@@ -0,0 +1,73 @@ +/* + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * Prints output. + * @param {String} src - Where the message is coming from. + * @param {String} txt - The text to print. + */ +function output(src, txt) { + // Handle DOMException: + if (txt.message) { + txt = txt.message; + } + txt = src + ': ' + txt; + if (window.domAutomationController) { + window.domAutomationController.send(txt); + } else { + txt += ' window.domAutomationController not found.'; + } + console.log(txt); +} + +/** + * Installs the payment handler. + */ +function install() { // eslint-disable-line no-unused-vars + if (!navigator.serviceWorker) { + output('install()', 'ServiceWorker API not found.'); + return; + } + + navigator.serviceWorker.getRegistration('app.js') + .then((registration) => { + if (registration) { + output( + 'serviceWorker.getRegistration()', + 'The ServiceWorker is already installed.'); + return; + } + navigator.serviceWorker.register('app.js') + .then(() => { + return navigator.serviceWorker.ready; + }) + .then((registration) => { + if (!registration.paymentManager) { + output( + 'serviceWorker.register()', + 'PaymentManager API not found.'); + return; + } + + registration.paymentManager.instruments + .set('123456', {name: 'Echo Pay', method: 'basic-card'}) + .then(() => { + output( + 'instruments.set()', + 'Payment handler installed.'); + }) + .catch((error) => { + output('instruments.set()', error); + }); + }) + .catch((error) => { + output('serviceWorker.register()', error); + }); + }) + .catch((error) => { + output('serviceWorker.getRegistration()', error); + }); +}
diff --git a/components/test/data/payments/show_promise/digital_goods.html b/components/test/data/payments/show_promise/digital_goods.html new file mode 100644 index 0000000..4c79a59 --- /dev/null +++ b/components/test/data/payments/show_promise/digital_goods.html
@@ -0,0 +1,22 @@ +<!doctype html> +<!-- +Copyright 2019 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> + <title>Show Promise Test For Digital Goods</title> + <link rel="stylesheet" type="text/css" href="../style.css"> +</head> +<body> + <div><button onclick="create()" id="create">Create</button></div> + <div><button onclick="buy()" id="buy">Buy</button></div> + <pre id="result"></pre> + <script src="../util.js"></script> + <script src="app_installer.js"></script> + <script src="digital_goods.js"></script> +</body> +</html> \ No newline at end of file
diff --git a/components/test/data/payments/show_promise/digital_goods.js b/components/test/data/payments/show_promise/digital_goods.js new file mode 100644 index 0000000..d5e76bd5 --- /dev/null +++ b/components/test/data/payments/show_promise/digital_goods.js
@@ -0,0 +1,44 @@ +/* + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +var request = null; + +/** + * Create an instance of PaymentRequest. + */ +function create() { // eslint-disable-line no-unused-vars + try { + request = new PaymentRequest([{supportedMethods: 'basic-card'}], { + total: + {label: 'PENDING TOTAL', amount: {currency: 'USD', value: '99.99'}}, + }); + } catch (error) { + print(error.message); + } +} + +/** + * Launch PaymentRequest with a show promise for digital goods. + */ +function buy() { // eslint-disable-line no-unused-vars + try { + request + .show(new Promise(function(resolve) { + resolve({ + total: {label: 'Total', amount: {currency: 'USD', value: '1.00'}}, + }); + })) + .then(function(result) { + print(JSON.stringify(result.details)); + return result.complete('success'); + }) + .catch(function(error) { + print(error); + }); + } catch (error) { + print(error); + } +}
diff --git a/components/test/data/payments/show_promise/invalid_details.html b/components/test/data/payments/show_promise/invalid_details.html new file mode 100644 index 0000000..beaaf898 --- /dev/null +++ b/components/test/data/payments/show_promise/invalid_details.html
@@ -0,0 +1,20 @@ +<!doctype html> +<!-- +Copyright 2019 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> + <title>Test for Show Promise with Invalid Details</title> + <link rel="stylesheet" type="text/css" href="../style.css"> +</head> +<body> + <div><button onclick="buy()" id="buy">Buy</button></div> + <pre id="result"></pre> + <script src="../util.js"></script> + <script src="invalid_details.js"></script> +</body> +</html> \ No newline at end of file
diff --git a/components/test/data/payments/show_promise/invalid_details.js b/components/test/data/payments/show_promise/invalid_details.js new file mode 100644 index 0000000..f760a258 --- /dev/null +++ b/components/test/data/payments/show_promise/invalid_details.js
@@ -0,0 +1,32 @@ +/* + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * Launch PaymentRequest with a show promise that resolve with invalid details. + */ +function buy() { // eslint-disable-line no-unused-vars + try { + new PaymentRequest([{supportedMethods: 'basic-card'}], { + total: { + label: 'PENDING TOTAL', + amount: {currency: 'USD', value: '99.99'}, + }, + }) + .show(new Promise(function(resolve) { + resolve({ + total: { + label: 'Total', + amount: {currency: 'USD', value: '-1.00'}, + }, + }); + })) + .catch(function(error) { + print(error); + }); + } catch (error) { + print(error.message); + } +}
diff --git a/components/test/data/payments/show_promise/reject.html b/components/test/data/payments/show_promise/reject.html new file mode 100644 index 0000000..82b1343 --- /dev/null +++ b/components/test/data/payments/show_promise/reject.html
@@ -0,0 +1,20 @@ +<!doctype html> +<!-- +Copyright 2019 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> + <title>Test for Rejecting the Show Promise</title> + <link rel="stylesheet" type="text/css" href="../style.css"> +</head> +<body> + <div><button onclick="buy()" id="buy">Buy</button></div> + <pre id="result"></pre> + <script src="../util.js"></script> + <script src="reject.js"></script> +</body> +</html> \ No newline at end of file
diff --git a/components/test/data/payments/show_promise/reject.js b/components/test/data/payments/show_promise/reject.js new file mode 100644 index 0000000..8630c7fc --- /dev/null +++ b/components/test/data/payments/show_promise/reject.js
@@ -0,0 +1,24 @@ +/* + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * Launch PaymentRequest with a show promise and reject that promise. + */ +function buy() { // eslint-disable-line no-unused-vars + try { + new PaymentRequest( + [{supportedMethods: 'basic-card'}], + {total: {label: 'Total', amount: {currency: 'USD', value: '1.00'}}}) + .show(new Promise(function(resolve, reject) { + reject(); + })) + .catch(function(error) { + print(error); + }); + } catch (error) { + print(error); + } +}
diff --git a/components/test/data/payments/show_promise/single_option_shipping.html b/components/test/data/payments/show_promise/single_option_shipping.html new file mode 100644 index 0000000..17e1736c --- /dev/null +++ b/components/test/data/payments/show_promise/single_option_shipping.html
@@ -0,0 +1,21 @@ +<!doctype html> +<!-- +Copyright 2019 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> + <title>Show Promise Test For Single-Option Shipping</title> + <link rel="stylesheet" type="text/css" href="../style.css"> +</head> +<body> + <div><button onclick="buy()" id="buy">Buy</button></div> + <pre id="result"></pre> + <script src="../util.js"></script> + <script src="app_installer.js"></script> + <script src="single_option_shipping.js"></script> +</body> +</html> \ No newline at end of file
diff --git a/components/test/data/payments/show_promise/single_option_shipping.js b/components/test/data/payments/show_promise/single_option_shipping.js new file mode 100644 index 0000000..b29a9238 --- /dev/null +++ b/components/test/data/payments/show_promise/single_option_shipping.js
@@ -0,0 +1,48 @@ +/* + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * Launch PaymentRequest with a show promise and a single pre-selected option + * for shipping worldwide. + */ +function buy() { // eslint-disable-line no-unused-vars + try { + new PaymentRequest( + [{supportedMethods: 'basic-card'}], { + total: { + label: 'PENDING TOTAL', + amount: {currency: 'USD', value: '99.99'}, + }, + shippingOptions: [{ + id: '1', + label: 'PENDING SHIPPING', + amount: {currency: 'USD', value: '99.99'}, + selected: true, + }], + }, + {requestShipping: true}) + .show(new Promise(function(resolve) { + resolve({ + total: {label: 'Total', amount: {currency: 'USD', value: '1.00'}}, + shippingOptions: [{ + id: '1', + label: 'Free shipping', + amount: {currency: 'USD', value: '0.00'}, + selected: true, + }], + }); + })) + .then(function(result) { + print(JSON.stringify(result.details)); + return result.complete('success'); + }) + .catch(function(error) { + print(error); + }); + } catch (error) { + print(error.message); + } +}
diff --git a/components/test/data/payments/show_promise/single_option_shipping_with_update.html b/components/test/data/payments/show_promise/single_option_shipping_with_update.html new file mode 100644 index 0000000..c1a1e64 --- /dev/null +++ b/components/test/data/payments/show_promise/single_option_shipping_with_update.html
@@ -0,0 +1,21 @@ +<!doctype html> +<!-- +Copyright 2019 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> + <title>Show Promise Test For Single-Option Shipping With Update</title> + <link rel="stylesheet" type="text/css" href="../style.css"> +</head> +<body> + <div><button onclick="buy()" id="buy">Buy</button></div> + <pre id="result"></pre> + <script src="../util.js"></script> + <script src="app_installer.js"></script> + <script src="single_option_shipping_with_update.js"></script> +</body> +</html> \ No newline at end of file
diff --git a/components/test/data/payments/show_promise/single_option_shipping_with_update.js b/components/test/data/payments/show_promise/single_option_shipping_with_update.js new file mode 100644 index 0000000..a3c1be0 --- /dev/null +++ b/components/test/data/payments/show_promise/single_option_shipping_with_update.js
@@ -0,0 +1,57 @@ +/* + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * Launch PaymentRequest with a show promise and a single pre-selected option + * for shipping worldwide and a handler for shipping address change events that + * does not change anything. + */ +function buy() { // eslint-disable-line no-unused-vars + var finalizedDetails = { + total: {label: 'Total', amount: {currency: 'USD', value: '1.00'}}, + shippingOptions: [{ + id: '1', + label: 'Free shipping', + amount: {currency: 'USD', value: '0.00'}, + selected: true, + }], + }; + + try { + var request = new PaymentRequest( + [{supportedMethods: 'basic-card'}], { + total: { + label: 'PENDING TOTAL', + amount: {currency: 'USD', value: '99.99'}, + }, + shippingOptions: [{ + id: '1', + label: 'PENDING SHIPPING', + amount: {currency: 'USD', value: '99.99'}, + selected: true, + }], + }, + {requestShipping: true}); + + request.addEventListener('shippingaddresschange', function(evt) { + evt.updateWith(finalizedDetails); + }); + + request + .show(new Promise(function(resolve) { + resolve(finalizedDetails); + })) + .then(function(result) { + print(JSON.stringify(result.details)); + return result.complete('success'); + }) + .catch(function(error) { + print(error); + }); + } catch (error) { + print(error.message); + } +}
diff --git a/components/test/data/payments/show_promise/timeout.html b/components/test/data/payments/show_promise/timeout.html new file mode 100644 index 0000000..7f29206 --- /dev/null +++ b/components/test/data/payments/show_promise/timeout.html
@@ -0,0 +1,20 @@ +<!doctype html> +<!-- +Copyright 2019 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> + <title>Test for Timing Out the Show Promise</title> + <link rel="stylesheet" type="text/css" href="../style.css"> +</head> +<body> + <div><button onclick="buy()" id="buy">Buy</button></div> + <pre id="result"></pre> + <script src="../util.js"></script> + <script src="timeout.js"></script> +</body> +</html> \ No newline at end of file
diff --git a/components/test/data/payments/show_promise/timeout.js b/components/test/data/payments/show_promise/timeout.js new file mode 100644 index 0000000..3bb80fe --- /dev/null +++ b/components/test/data/payments/show_promise/timeout.js
@@ -0,0 +1,22 @@ +/* + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * Launch PaymentRequest with a show promise and don't resolve or reject it. + */ +function buy() { // eslint-disable-line no-unused-vars + try { + new PaymentRequest( + [{supportedMethods: 'basic-card'}], + {total: {label: 'Total', amount: {currency: 'USD', value: '1.00'}}}) + .show(new Promise(function(resolve) { /* Intentionally empty. */ })) + .catch(function(error) { + print(error); + }); + } catch (error) { + print(error); + } +}
diff --git a/components/test/data/payments/show_promise/unsupported.html b/components/test/data/payments/show_promise/unsupported.html new file mode 100644 index 0000000..e3b00fe9 --- /dev/null +++ b/components/test/data/payments/show_promise/unsupported.html
@@ -0,0 +1,20 @@ +<!doctype html> +<!-- +Copyright 2019 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> + <title>Test for Show Promise with Unsupported Payment Method Identifier</title> + <link rel="stylesheet" type="text/css" href="../style.css"> +</head> +<body> + <div><button onclick="buy()" id="buy">Buy</button></div> + <pre id="result"></pre> + <script src="../util.js"></script> + <script src="unsupported.js"></script> +</body> +</html> \ No newline at end of file
diff --git a/components/test/data/payments/show_promise/unsupported.js b/components/test/data/payments/show_promise/unsupported.js new file mode 100644 index 0000000..6196ee22 --- /dev/null +++ b/components/test/data/payments/show_promise/unsupported.js
@@ -0,0 +1,31 @@ +/* + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * Launch PaymentRequest with a show promise and an unsupported payment method + * identifier. + */ +function buy() { // eslint-disable-line no-unused-vars + try { + new PaymentRequest([{supportedMethods: 'foo'}], { + total: + {label: 'PENDING TOTAL', amount: {currency: 'USD', value: '99.99'}}, + }) + .show(new Promise(function(resolve) { + resolve({ + total: { + label: 'Total', + amount: {currency: 'USD', value: '1.00'}, + }, + }); + })) + .catch(function(error) { + print(error); + }); + } catch (error) { + print(error); + } +}
diff --git a/components/test/data/payments/show_promise/us_only_shipping.html b/components/test/data/payments/show_promise/us_only_shipping.html new file mode 100644 index 0000000..d5af7ae --- /dev/null +++ b/components/test/data/payments/show_promise/us_only_shipping.html
@@ -0,0 +1,21 @@ +<!doctype html> +<!-- +Copyright 2019 The Chromium Authors. All rights reserved. +Use of this source code is governed by a BSD-style license that can be +found in the LICENSE file. +--> +<html lang="en"> +<head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1"> + <title>Show Promise Test For US-Only Shipping</title> + <link rel="stylesheet" type="text/css" href="../style.css"> +</head> +<body> + <div><button onclick="buy()" id="buy">Buy</button></div> + <pre id="result"></pre> + <script src="../util.js"></script> + <script src="app_installer.js"></script> + <script src="us_only_shipping.js"></script> +</body> +</html> \ No newline at end of file
diff --git a/components/test/data/payments/show_promise/us_only_shipping.js b/components/test/data/payments/show_promise/us_only_shipping.js new file mode 100644 index 0000000..af8480f --- /dev/null +++ b/components/test/data/payments/show_promise/us_only_shipping.js
@@ -0,0 +1,56 @@ +/* + * Copyright 2019 The Chromium Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +/** + * Launch PaymentRequest with a show promise and US-only shipping. + */ +function buy() { // eslint-disable-line no-unused-vars + var detailsForUSAddress = { + shippingOptions: [{ + id: '1', + label: 'Free shipping', + amount: {currency: 'USD', value: '0.00'}, + selected: true, + }], + }; + + var detailsForNonUSAddress = {error: 'Cannot ship outside of US.'}; + + try { + var request = new PaymentRequest( + [{supportedMethods: 'basic-card'}], { + total: { + label: 'PENDING TOTAL', + amount: {currency: 'USD', value: '99.99'}, + }, + }, + {requestShipping: true}); + + request.addEventListener('shippingaddresschange', function(evt) { + if (request.shippingAddress.country === 'US') { + evt.updateWith(detailsForUSAddress); + } else { + evt.updateWith(detailsForNonUSAddress); + } + }); + + request + .show(new Promise(function(resolve) { + resolve({ + total: {label: 'Total', amount: {currency: 'USD', value: '1.00'}}, + }); + })) + .then(function(result) { + print(JSON.stringify(result.details)); + return result.complete('success'); + }) + .catch(function(error) { + print(error); + }); + } catch (error) { + print(error.message); + } +}
diff --git a/components/viz/service/display_embedder/buffer_queue.cc b/components/viz/service/display_embedder/buffer_queue.cc index 6f00149..a813220 100644 --- a/components/viz/service/display_embedder/buffer_queue.cc +++ b/components/viz/service/display_embedder/buffer_queue.cc
@@ -17,6 +17,7 @@ #include "ui/display/types/display_snapshot.h" #include "ui/gfx/gpu_memory_buffer.h" #include "ui/gfx/skia_util.h" +#include "ui/gl/gl_enums.h" namespace viz { @@ -53,13 +54,20 @@ if (!current_surface_) current_surface_ = GetNextSurface(); - if (current_surface_) { - gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, - texture_target_, current_surface_->texture, 0); - if (current_surface_->stencil) { - gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, - GL_RENDERBUFFER, current_surface_->stencil); - } + if (!current_surface_) + return; + gl_->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + texture_target_, current_surface_->texture, 0); + +#if DCHECK_IS_ON() && defined(OS_CHROMEOS) + const GLenum result = gl_->CheckFramebufferStatus(GL_FRAMEBUFFER); + if (result != GL_FRAMEBUFFER_COMPLETE) + DLOG(ERROR) << " Incomplete fb: " << gl::GLEnums::GetStringError(result); +#endif + + if (current_surface_->stencil) { + gl_->FramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_RENDERBUFFER, current_surface_->stencil); } } @@ -146,8 +154,9 @@ const gfx::ColorSpace& color_space, bool use_stencil) { if (size == size_ && color_space == color_space_ && - use_stencil == use_stencil_) + use_stencil == use_stencil_) { return; + } #if !defined(OS_MACOSX) // TODO(ccameron): This assert is being hit on Mac try jobs. Determine if that // is cause for concern or if it is benign.
diff --git a/content/browser/browsing_instance.cc b/content/browser/browsing_instance.cc index 00b87767..d48d1441 100644 --- a/content/browser/browsing_instance.cc +++ b/content/browser/browsing_instance.cc
@@ -78,8 +78,10 @@ // No current SiteInstance for this site, so let's create one. scoped_refptr<SiteInstanceImpl> instance = new SiteInstanceImpl(this); - // Set the site of this new SiteInstance, which will register it with us. - instance->SetSite(url); + // Set the site of this new SiteInstance, which will register it with us, + // unless this URL should leave the SiteInstance's site unassigned. + if (SiteInstance::ShouldAssignSiteForURL(url)) + instance->SetSite(url); return instance; }
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 28b2e1b..758e5ee 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -209,14 +209,14 @@ // Blink and //content. if (IsSecMetadataEnabled() && IsOriginSecure(url)) { std::string site_value = "cross-site"; - std::string user_value = has_user_gesture ? "?T" : std::string(); + std::string user_value = has_user_gesture ? "?1" : std::string(); // Navigations that aren't triggerable from the web (e.g. typing in the // address bar, or clicking a bookmark) are labeled as 'none'. Webby // navigations compare the |initiator_origin| to the navigation target. if (!PageTransitionIsWebTriggerable(transition)) { site_value = "none"; - user_value = "?T"; + user_value = "?1"; } else if (initiator_origin) { url::Origin target_origin = url::Origin::Create(url); if (initiator_origin->IsSameOriginWith(target_origin)) {
diff --git a/content/browser/frame_host/render_frame_host_manager_browsertest.cc b/content/browser/frame_host/render_frame_host_manager_browsertest.cc index b608bdf..251b1008 100644 --- a/content/browser/frame_host/render_frame_host_manager_browsertest.cc +++ b/content/browser/frame_host/render_frame_host_manager_browsertest.cc
@@ -5692,4 +5692,102 @@ EXPECT_EQ(speculative_rph, web_contents->GetMainFrame()->GetProcess()); } +// ContentBrowserClient that skips assigning a site URL for a given URL. +class DontAssignSiteContentBrowserClient : public TestContentBrowserClient { + public: + // Any visit to |url_to_skip| will not cause the site to be assigned to the + // SiteInstance. + explicit DontAssignSiteContentBrowserClient(const GURL& url_to_skip) + : url_to_skip_(url_to_skip) {} + + bool ShouldAssignSiteForURL(const GURL& url) override { + return url != url_to_skip_; + } + + private: + GURL url_to_skip_; + + DISALLOW_COPY_AND_ASSIGN(DontAssignSiteContentBrowserClient); +}; + +// Ensure that coming back to a NavigationEntry with a previously unassigned +// SiteInstance (which is now used for another site) properly switches processes +// and SiteInstances. See https://crbug.com/945399. +IN_PROC_BROWSER_TEST_F(RenderFrameHostManagerTest, + NavigateWithUnassignedSiteInstance) { + ASSERT_TRUE(embedded_test_server()->Start()); + WebContentsImpl* web_contents = + static_cast<WebContentsImpl*>(shell()->web_contents()); + + // Navigate to a URL that does not assign site URLs. + GURL url1(embedded_test_server()->GetURL("a.com", "/title1.html")); + DontAssignSiteContentBrowserClient content_browser_client(url1); + ContentBrowserClient* old_client = + SetBrowserClientForTesting(&content_browser_client); + EXPECT_TRUE(NavigateToURL(shell(), url1)); + EXPECT_EQ(url1, web_contents->GetLastCommittedURL()); + scoped_refptr<SiteInstanceImpl> instance1( + web_contents->GetMainFrame()->GetSiteInstance()); + RenderProcessHost* process1 = instance1->GetProcess(); + EXPECT_EQ(GURL(), instance1->GetSiteURL()); + + // Navigate to foo.com, which uses the previous SiteInstance and sets its site + // URL. + GURL url2(embedded_test_server()->GetURL("foo.com", "/title1.html")); + EXPECT_TRUE(NavigateToURL(shell(), url2)); + EXPECT_EQ(instance1, web_contents->GetMainFrame()->GetSiteInstance()); + EXPECT_EQ(GURL("http://foo.com"), instance1->GetSiteURL()); + + // Navigate to bar.com, which destroys the previous RenderProcessHost. + GURL url3(embedded_test_server()->GetURL("bar.com", "/title1.html")); + RenderProcessHostWatcher exit_observer( + process1, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); + EXPECT_TRUE(NavigateToURL(shell(), url3)); + exit_observer.Wait(); + EXPECT_NE(instance1, web_contents->GetMainFrame()->GetSiteInstance()); + + // At this point, process1 is deleted, and the first entry is unfortunately + // pointing to instance1, which has been locked to url2 and has no process. + EXPECT_FALSE(instance1->HasProcess()); + if (AreAllSitesIsolatedForTesting()) { + // In site-per-process, we cannot use foo.com's SiteInstance for a.com. + EXPECT_TRUE(instance1->HasWrongProcessForURL(url1)); + } else { + // If neither foo.com nor a.com require dedicated processes, then we can use + // the same process. + EXPECT_FALSE(instance1->HasWrongProcessForURL(url1)); + } + + // TODO(creis): Enable the rest of the test when https://crbug.com/793127 is + // fixed, since this currently fails with a DCHECK in SiteProcessCountTracker. +#if 0 + // Go back to the chrome-native:// URL's entry, which should swap to a new + // SiteInstance with an unused site URL. + TestNavigationObserver observer(web_contents); + web_contents->GetController().GoToOffset(-2); + observer.Wait(); + scoped_refptr<SiteInstanceImpl> new_instance = + web_contents->GetMainFrame()->GetSiteInstance(); + EXPECT_EQ(url1, web_contents->GetLastCommittedURL()); + if (AreAllSitesIsolatedForTesting()) { + EXPECT_NE(instance1, new_instance); + EXPECT_EQ(GURL(), new_instance->GetSiteURL()); + } else { + EXPECT_EQ(instance1, new_instance); + } + EXPECT_TRUE(new_instance->HasProcess()); + + // Because url1 does not set a site URL, it should not lock the new process + // either, so that it can be used for subsequent navigations. + content::RenderProcessHost* new_process = new_instance->GetProcess(); + auto* policy = ChildProcessSecurityPolicy::GetInstance(); + EXPECT_TRUE( + policy->CanAccessDataForOrigin(new_process->GetID(), url1)); + EXPECT_TRUE( + policy->CanAccessDataForOrigin(new_process->GetID(), url2)); +#endif + + SetBrowserClientForTesting(old_client); +} + } // namespace content
diff --git a/content/browser/frame_host/sec_fetch_browsertest.cc b/content/browser/frame_host/sec_fetch_browsertest.cc index d55e69e2..5b0a48b 100644 --- a/content/browser/frame_host/sec_fetch_browsertest.cc +++ b/content/browser/frame_host/sec_fetch_browsertest.cc
@@ -88,9 +88,9 @@ } { - // Sec-Fetch-User: ?T + // Sec-Fetch-User: ?1 NavigateForHeader("Sec-Fetch-User"); - EXPECT_EQ("?T", GetContent()); + EXPECT_EQ("?1", GetContent()); } }
diff --git a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc index 1d52043..684cae99 100644 --- a/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc +++ b/content/browser/indexed_db/indexed_db_dispatcher_host_unittest.cc
@@ -1165,7 +1165,8 @@ context_impl_->RemoveObserver(&observer); } -TEST_F(IndexedDBDispatcherHostTest, NotifyIndexedDBContentChanged) { +// The test is flaky. See https://crbug.com/879213 +TEST_F(IndexedDBDispatcherHostTest, DISABLED_NotifyIndexedDBContentChanged) { const int64_t kDBVersion1 = 1; const int64_t kDBVersion2 = 2; const int64_t kTransactionId1 = 1;
diff --git a/content/browser/renderer_host/frame_connector_delegate.cc b/content/browser/renderer_host/frame_connector_delegate.cc index 39f910a..c0d82a9 100644 --- a/content/browser/renderer_host/frame_connector_delegate.cc +++ b/content/browser/renderer_host/frame_connector_delegate.cc
@@ -48,7 +48,9 @@ render_widget_host->SetAutoResize(visual_properties.auto_resize_enabled, visual_properties.min_size_for_auto_resize, visual_properties.max_size_for_auto_resize); - render_widget_host->SetPageScaleFactor(visual_properties.page_scale_factor); + render_widget_host->SetPageScaleState( + visual_properties.page_scale_factor, + visual_properties.is_pinch_gesture_active); render_widget_host->SynchronizeVisualProperties(); }
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc index c9a555e7..edfc500c 100644 --- a/content/browser/renderer_host/render_widget_host_impl.cc +++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -422,6 +422,7 @@ visual_properties_ack_pending_(false), auto_resize_enabled_(false), page_scale_factor_(1.f), + is_pinch_gesture_active_(false), waiting_for_screen_rects_ack_(false), is_unresponsive_(false), in_flight_event_count_(0), @@ -898,6 +899,7 @@ visual_properties->max_size_for_auto_resize = max_size_for_auto_resize_; visual_properties->page_scale_factor = page_scale_factor_; + visual_properties->is_pinch_gesture_active = is_pinch_gesture_active_; if (view_) { visual_properties->new_size = view_->GetRequestedRendererSize(); @@ -984,7 +986,9 @@ old_visual_properties_->capture_sequence_number != visual_properties->capture_sequence_number || old_visual_properties_->page_scale_factor != - visual_properties->page_scale_factor; + visual_properties->page_scale_factor || + old_visual_properties_->is_pinch_gesture_active != + visual_properties->is_pinch_gesture_active; // We should throttle sending updated VisualProperties to the renderer to // the rate of commit. This ensures we don't overwhelm the renderer with @@ -2165,8 +2169,10 @@ max_size_for_auto_resize_ = max_size; } -void RenderWidgetHostImpl::SetPageScaleFactor(float page_scale_factor) { +void RenderWidgetHostImpl::SetPageScaleState(float page_scale_factor, + bool is_pinch_gesture_active) { page_scale_factor_ = page_scale_factor; + is_pinch_gesture_active_ = is_pinch_gesture_active; } void RenderWidgetHostImpl::Destroy(bool also_delete) {
diff --git a/content/browser/renderer_host/render_widget_host_impl.h b/content/browser/renderer_host/render_widget_host_impl.h index 5264464..02e16b3f 100644 --- a/content/browser/renderer_host/render_widget_host_impl.h +++ b/content/browser/renderer_host/render_widget_host_impl.h
@@ -562,8 +562,8 @@ const gfx::Size& min_size, const gfx::Size& max_size); - // Allows the main frame's page scale factor to be tracked. - void SetPageScaleFactor(float page_scale_factor); + // Allows the main frame's page scale state to be tracked. + void SetPageScaleState(float page_scale_factor, bool is_pinch_gesture_active); // Fills in the |visual_properties| struct. // Returns |false| if the update is redundant, |true| otherwise. @@ -1018,6 +1018,8 @@ // The page-scale factor of the main-frame. float page_scale_factor_; + // True when the renderer is currently undergoing a pinch-zoom gesture. + bool is_pinch_gesture_active_; bool waiting_for_screen_rects_ack_; gfx::Rect last_view_screen_rect_;
diff --git a/content/browser/site_instance_impl.cc b/content/browser/site_instance_impl.cc index 1612c78..77bf6dc 100644 --- a/content/browser/site_instance_impl.cc +++ b/content/browser/site_instance_impl.cc
@@ -217,6 +217,8 @@ } void SiteInstanceImpl::SetSite(const GURL& url) { + // TODO(creis): Consider calling ShouldAssignSiteForURL internally, rather + // than before multiple call sites. See https://crbug.com/949220. TRACE_EVENT2("navigation", "SiteInstanceImpl::SetSite", "site id", id_, "url", url.possibly_invalid_spec()); // A SiteInstance's site should not change. @@ -287,14 +289,6 @@ } bool SiteInstanceImpl::HasWrongProcessForURL(const GURL& url) { - // Having no process isn't a problem, since we'll assign it correctly. - // Note that HasProcess() may return true if process_ is null, in - // process-per-site cases where there's an existing process available. - // We want to use such a process in the IsSuitableHost check, so we - // may end up assigning process_ in the GetProcess() call below. - if (!HasProcess()) - return false; - // If the URL to navigate to can be associated with any site instance, // we want to keep it in the same process. if (IsRendererDebugURL(url)) @@ -321,6 +315,37 @@ // GetRelatedSiteInstance(url). browsing_instance_->GetSiteAndLockForURL( url, /* allow_default_instance */ true, &site_url, &origin_lock); + + // Note that HasProcess() may return true if process_ is null, in + // process-per-site cases where there's an existing process available. + // We want to use such a process in the IsSuitableHost check, so we + // may end up assigning process_ in the GetProcess() call below. + if (!HasProcess()) { + // If there is no process or site, then this is a new SiteInstance that can + // be used for anything. + if (!HasSite()) + return false; + + // If there is no process but there is a site, then the process must have + // been discarded after we navigated away. If the site URLs match, then it + // is safe to use this SiteInstance. + if (GetSiteURL() == site_url) + return false; + + // If the site URLs do not match, but neither this SiteInstance nor the + // destination site_url require dedicated processes, then it is safe to use + // this SiteInstance. + if (!RequiresDedicatedProcess() && + !DoesSiteRequireDedicatedProcess(GetIsolationContext(), site_url)) { + return false; + } + + // Otherwise, there's no process, the site URLs don't match, and at least + // one of them requires a dedicated process, so it is not safe to use this + // SiteInstance. + return true; + } + return !RenderProcessHostImpl::IsSuitableHost( GetProcess(), browsing_instance_->GetBrowserContext(), GetIsolationContext(), site_url, origin_lock);
diff --git a/content/browser/site_instance_impl_unittest.cc b/content/browser/site_instance_impl_unittest.cc index 86379ad6..628d64b 100644 --- a/content/browser/site_instance_impl_unittest.cc +++ b/content/browser/site_instance_impl_unittest.cc
@@ -721,13 +721,13 @@ EXPECT_FALSE(instance->HasSite()); EXPECT_TRUE(instance->GetSiteURL().is_empty()); + // Check prior to assigning a site or process to the instance, which is + // expected to return false to allow the SiteInstance to be used for anything. + EXPECT_FALSE(instance->HasWrongProcessForURL(GURL("http://google.com"))); + instance->SetSite(GURL("http://evernote.com/")); EXPECT_TRUE(instance->HasSite()); - // Check prior to "assigning" a process to the instance, which is expected - // to return false due to not being attached to any process yet. - EXPECT_FALSE(instance->HasWrongProcessForURL(GURL("http://google.com"))); - // The call to GetProcess actually creates a new real process, which works // fine, but might be a cause for problems in different contexts. host.reset(instance->GetProcess()); @@ -779,13 +779,13 @@ scoped_refptr<SiteInstanceImpl> instance( SiteInstanceImpl::Create(browser_context.get())); + // Check prior to assigning a site or process to the instance, which is + // expected to return false to allow the SiteInstance to be used for anything. + EXPECT_FALSE(instance->HasWrongProcessForURL(GURL("http://google.com"))); + instance->SetSite(GURL("http://evernote.com/")); EXPECT_TRUE(instance->HasSite()); - // Check prior to "assigning" a process to the instance, which is expected - // to return false due to not being attached to any process yet. - EXPECT_FALSE(instance->HasWrongProcessForURL(GURL("http://google.com"))); - // The call to GetProcess actually creates a new real process, which works // fine, but might be a cause for problems in different contexts. host.reset(instance->GetProcess());
diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc index e870f17..bbc5c8d 100644 --- a/content/browser/site_per_process_browsertest.cc +++ b/content/browser/site_per_process_browsertest.cc
@@ -10880,6 +10880,17 @@ RenderFrameSubmissionObserver observer_c(child_c); RenderFrameSubmissionObserver observer_d(child_d); + // Monitor visual sync messages coming from the mainframe to make sure + // |is_pinch_gesture_active| goes true during the pinch gesture. + scoped_refptr<SynchronizeVisualPropertiesMessageFilter> filter_mainframe = + new SynchronizeVisualPropertiesMessageFilter(); + root->current_frame_host()->GetProcess()->AddFilter(filter_mainframe.get()); + // Monitor frame sync messages coming from child_b as it will need to + // relay them to child_d. + scoped_refptr<SynchronizeVisualPropertiesMessageFilter> filter_child_b = + new SynchronizeVisualPropertiesMessageFilter(); + child_b->current_frame_host()->GetProcess()->AddFilter(filter_child_b.get()); + // We need to observe a root frame submission to pick up the initial page // scale factor. observer_a.WaitForAnyFrameSubmission(); @@ -10923,6 +10934,17 @@ observer_b.WaitForExternalPageScaleFactor(target_page_scale, kScaleTolerance); observer_c.WaitForExternalPageScaleFactor(target_page_scale, kScaleTolerance); observer_d.WaitForExternalPageScaleFactor(target_page_scale, kScaleTolerance); + + // The change in |is_pinch_gesture_active| that signals the end of the pinch + // gesture will occur sometime after the ack for GesturePinchEnd, so we need + // to wait for it from each renderer. If it's never seen, the test fails by + // timing out. + filter_mainframe->WaitForPinchGestureEnd(); + EXPECT_TRUE(filter_mainframe->pinch_gesture_active_set()); + EXPECT_TRUE(filter_mainframe->pinch_gesture_active_cleared()); + filter_child_b->WaitForPinchGestureEnd(); + EXPECT_TRUE(filter_child_b->pinch_gesture_active_set()); + EXPECT_TRUE(filter_child_b->pinch_gesture_active_cleared()); } // Verify that sandbox flags specified by a CSP header are properly inherited by
diff --git a/content/browser/web_contents/web_contents_impl_unittest.cc b/content/browser/web_contents/web_contents_impl_unittest.cc index 526d73f..c1bfa288 100644 --- a/content/browser/web_contents/web_contents_impl_unittest.cc +++ b/content/browser/web_contents/web_contents_impl_unittest.cc
@@ -27,6 +27,7 @@ #include "content/common/frame_messages.h" #include "content/common/input/synthetic_web_input_event_builders.h" #include "content/common/view_messages.h" +#include "content/public/browser/child_process_security_policy.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/global_request_id.h" #include "content/public/browser/interstitial_page_delegate.h" @@ -1109,7 +1110,7 @@ // Tests that if we go back twice (same-site then cross-site), and the cross- // site RFH commits first, we ignore the now-swapped-out RFH's commit. TEST_F(WebContentsImplTest, CrossSiteNavigationBackOldNavigationIgnored) { - // Start with a web ui page, which gets a new RVH with WebUI bindings. + // Start with a web ui page, which gets a new RFH with WebUI bindings. GURL url1(std::string(kChromeUIScheme) + "://" + std::string(kChromeUIGpuHost)); NavigationSimulator::NavigateAndCommitFromBrowser(contents(), url1); @@ -1170,6 +1171,9 @@ webui_rfh = contents()->GetPendingMainFrame(); // DidNavigate from the second back. + // Note that the process in instance1 is gone at this point, but we will still + // use instance1 and entry1 because HasWrongProcessForURL will return false + // when there is no process and the site URL matches. back_navigation2->Commit(); // That should have landed us on the first entry. @@ -1179,6 +1183,12 @@ contents()->TestDidNavigate(google_rfh, entry2->GetUniqueID(), false, url2, ui::PAGE_TRANSITION_TYPED); EXPECT_EQ(entry1, controller().GetLastCommittedEntry()); + + // The newly created process for url1 should be locked to chrome://gpu. + RenderProcessHost* new_process = contents()->GetMainFrame()->GetProcess(); + auto* policy = content::ChildProcessSecurityPolicy::GetInstance(); + EXPECT_TRUE(policy->CanAccessDataForOrigin(new_process->GetID(), url1)); + EXPECT_FALSE(policy->CanAccessDataForOrigin(new_process->GetID(), url2)); } // Test that during a slow cross-site navigation, a sub-frame navigation in the
diff --git a/content/browser/webauth/authenticator_impl_unittest.cc b/content/browser/webauth/authenticator_impl_unittest.cc index 0c78440..86975327 100644 --- a/content/browser/webauth/authenticator_impl_unittest.cc +++ b/content/browser/webauth/authenticator_impl_unittest.cc
@@ -282,15 +282,19 @@ return criteria; } -std::vector<PublicKeyCredentialDescriptorPtr> GetTestAllowCredentials() { +std::vector<PublicKeyCredentialDescriptorPtr> GetTestCredentials( + size_t num_credentials = 1) { std::vector<PublicKeyCredentialDescriptorPtr> descriptors; - auto credential = PublicKeyCredentialDescriptor::New(); - credential->type = PublicKeyCredentialType::PUBLIC_KEY; - std::vector<uint8_t> id(32, 0x0A); - credential->id = id; - credential->transports.push_back(AuthenticatorTransport::USB); - credential->transports.push_back(AuthenticatorTransport::BLE); - descriptors.push_back(std::move(credential)); + for (size_t i = 0; i < num_credentials; i++) { + DCHECK(i <= std::numeric_limits<uint8_t>::max()); + std::vector<uint8_t> id(32u, static_cast<uint8_t>(i)); + auto credential = PublicKeyCredentialDescriptor::New(); + credential->type = PublicKeyCredentialType::PUBLIC_KEY; + credential->id = id; + credential->transports.push_back(AuthenticatorTransport::USB); + credential->transports.push_back(AuthenticatorTransport::BLE); + descriptors.push_back(std::move(credential)); + } return descriptors; } @@ -315,7 +319,7 @@ options->adjusted_timeout = base::TimeDelta::FromMinutes(1); options->user_verification = blink::mojom::UserVerificationRequirement::PREFERRED; - options->allow_credentials = GetTestAllowCredentials(); + options->allow_credentials = GetTestCredentials(); return options; } @@ -1119,7 +1123,7 @@ GetTestPublicKeyCredentialCreationOptions(); // Exclude the one already registered credential. - options->exclude_credentials = GetTestAllowCredentials(); + options->exclude_credentials = GetTestCredentials(); ASSERT_TRUE(scoped_virtual_device.mutable_state()->InjectRegistration( options->exclude_credentials[0]->id, kTestRelyingPartyId)); @@ -2361,7 +2365,7 @@ PublicKeyCredentialCreationOptionsPtr options = GetTestPublicKeyCredentialCreationOptions(); - options->exclude_credentials = GetTestAllowCredentials(); + options->exclude_credentials = GetTestCredentials(); ASSERT_TRUE(scoped_virtual_device.mutable_state()->InjectRegistration( options->exclude_credentials[0]->id, kTestRelyingPartyId)); @@ -2493,6 +2497,74 @@ } } +TEST_F(AuthenticatorImplTest, MakeCredentialWithLargeExcludeList) { + TestServiceManagerContext smc; + NavigateAndCommit(GURL(kTestOrigin1)); + + for (bool has_excluded_credential : {false, true}) { + SCOPED_TRACE(::testing::Message() + << "has_excluded_credential=" << has_excluded_credential); + + device::test::ScopedVirtualFidoDevice virtual_device; + device::VirtualCtap2Device::Config config; + config.reject_large_allow_and_exclude_lists = true; + virtual_device.SetCtap2Config(config); + + PublicKeyCredentialCreationOptionsPtr options = + GetTestPublicKeyCredentialCreationOptions(); + options->exclude_credentials = GetTestCredentials(/*num_credentials=*/10); + if (has_excluded_credential) { + ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration( + options->exclude_credentials.back()->id, kTestRelyingPartyId)); + } + TestMakeCredentialCallback callback_receiver; + + AuthenticatorPtr authenticator = ConnectToAuthenticator(); + authenticator->MakeCredential(std::move(options), + callback_receiver.callback()); + base::RunLoop().RunUntilIdle(); + callback_receiver.WaitForCallback(); + EXPECT_EQ(callback_receiver.status(), + has_excluded_credential ? AuthenticatorStatus::CREDENTIAL_EXCLUDED + : AuthenticatorStatus::SUCCESS); + } +} + +TEST_F(AuthenticatorImplTest, GetAssertionWithLargeAllowList) { + TestServiceManagerContext smc; + NavigateAndCommit(GURL(kTestOrigin1)); + + for (bool has_allowed_credential : {false, true}) { + SCOPED_TRACE(::testing::Message() + << "has_allowed_credential=" << has_allowed_credential); + + device::test::ScopedVirtualFidoDevice virtual_device; + device::VirtualCtap2Device::Config config; + config.reject_large_allow_and_exclude_lists = true; + virtual_device.SetCtap2Config(config); + + AuthenticatorPtr authenticator = ConnectToAuthenticator(); + + PublicKeyCredentialRequestOptionsPtr options = + GetTestPublicKeyCredentialRequestOptions(); + options->allow_credentials = GetTestCredentials(/*num_credentials=*/10); + if (has_allowed_credential) { + ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration( + options->allow_credentials.back()->id, kTestRelyingPartyId)); + } + + TestGetAssertionCallback callback_receiver; + authenticator->GetAssertion(std::move(options), + callback_receiver.callback()); + base::RunLoop().RunUntilIdle(); + callback_receiver.WaitForCallback(); + EXPECT_EQ(callback_receiver.status(), + has_allowed_credential + ? AuthenticatorStatus::SUCCESS + : AuthenticatorStatus::CREDENTIAL_NOT_RECOGNIZED); + } +} + class UVAuthenticatorImplTest : public AuthenticatorImplTest { public: UVAuthenticatorImplTest() = default;
diff --git a/content/common/frame_messages.h b/content/common/frame_messages.h index 4784e99..48b2fe1 100644 --- a/content/common/frame_messages.h +++ b/content/common/frame_messages.h
@@ -265,6 +265,7 @@ IPC_STRUCT_TRAITS_MEMBER(capture_sequence_number) IPC_STRUCT_TRAITS_MEMBER(zoom_level) IPC_STRUCT_TRAITS_MEMBER(page_scale_factor) + IPC_STRUCT_TRAITS_MEMBER(is_pinch_gesture_active) IPC_STRUCT_TRAITS_MEMBER(local_surface_id_allocation) IPC_STRUCT_TRAITS_END()
diff --git a/content/common/frame_visual_properties.h b/content/common/frame_visual_properties.h index b93180d..c897b9b 100644 --- a/content/common/frame_visual_properties.h +++ b/content/common/frame_visual_properties.h
@@ -44,7 +44,10 @@ // (0 is the default value which results in 1.0 zoom factor.) double zoom_level = 0; + // Tracks the page-scale factor and whether the frame is currently in an + // active pinch-zoom gesture. float page_scale_factor = 1.f; + bool is_pinch_gesture_active = false; // The time at which the viz::LocalSurfaceId used to submit this was // allocated.
diff --git a/content/common/navigation_params.h b/content/common/navigation_params.h index 7ce18aaf5..eff2dc20 100644 --- a/content/common/navigation_params.h +++ b/content/common/navigation_params.h
@@ -98,7 +98,7 @@ kOpenerCrossOrigin = 5, // The navigation was initiated from or occurred in an iframe with - // |kSandboxDownloads| flag set and without user activation. + // |WebSandboxFlags::kDownloads| flag set and without user activation. kSandboxNoGesture = 7, // The navigation was initiated from or occurred in an ad frame without user
diff --git a/content/common/visual_properties.h b/content/common/visual_properties.h index ed6f914..dcccf0b 100644 --- a/content/common/visual_properties.h +++ b/content/common/visual_properties.h
@@ -83,6 +83,10 @@ // This represents the page's scale factor, which changes during pinch zoom. // It needs to be shared with subframes. float page_scale_factor = 1.f; + + // Indicates whether a pinch gesture is currently active. Originates in the + // main frame's renderer, and needs to be shared with subframes. + bool is_pinch_gesture_active = false; }; } // namespace content
diff --git a/content/common/widget_messages.h b/content/common/widget_messages.h index 84f6662a..fcda7ced 100644 --- a/content/common/widget_messages.h +++ b/content/common/widget_messages.h
@@ -63,6 +63,7 @@ IPC_STRUCT_TRAITS_MEMBER(capture_sequence_number) IPC_STRUCT_TRAITS_MEMBER(zoom_level) IPC_STRUCT_TRAITS_MEMBER(page_scale_factor) + IPC_STRUCT_TRAITS_MEMBER(is_pinch_gesture_active) IPC_STRUCT_TRAITS_END() // Traits for WebDeviceEmulationParams.
diff --git a/content/public/test/browser_test_utils.cc b/content/public/test/browser_test_utils.cc index 74a2c98..b6de992 100644 --- a/content/public/test/browser_test_utils.cc +++ b/content/public/test/browser_test_utils.cc
@@ -3155,6 +3155,20 @@ void SynchronizeVisualPropertiesMessageFilter::OnSynchronizeVisualProperties( const viz::FrameSinkId& frame_sink_id, const FrameVisualProperties& visual_properties) { + // Monitor |is_pinch_gesture_active| to determine when pinch gestures begin + // and end. + if (visual_properties.is_pinch_gesture_active && + !last_pinch_gesture_active_) { + pinch_gesture_active_set_ = true; + } + if (!visual_properties.is_pinch_gesture_active && + last_pinch_gesture_active_) { + pinch_gesture_active_cleared_ = true; + if (pinch_end_run_loop_) + pinch_end_run_loop_->Quit(); + } + last_pinch_gesture_active_ = visual_properties.is_pinch_gesture_active; + gfx::Rect screen_space_rect_in_dip = visual_properties.screen_space_rect; if (IsUseZoomForDSFEnabled()) { screen_space_rect_in_dip = @@ -3236,6 +3250,14 @@ return false; } +void SynchronizeVisualPropertiesMessageFilter::WaitForPinchGestureEnd() { + if (pinch_gesture_active_cleared_) + return; + DCHECK(!pinch_end_run_loop_); + pinch_end_run_loop_ = std::make_unique<base::RunLoop>(); + pinch_end_run_loop_->Run(); +} + RenderWidgetHostMouseEventMonitor::RenderWidgetHostMouseEventMonitor( RenderWidgetHost* host) : host_(host), event_received_(false) {
diff --git a/content/public/test/browser_test_utils.h b/content/public/test/browser_test_utils.h index 7c11f9c..69c48d88 100644 --- a/content/public/test/browser_test_utils.h +++ b/content/public/test/browser_test_utils.h
@@ -1574,6 +1574,7 @@ // BrowserPluginHostMsg_SynchronizeVisualProperties messages. This allows the // message to continue to the target child so that processing can be verified by // tests. +// It also monitors for GesturePinchBegin/End events. class SynchronizeVisualPropertiesMessageFilter : public content::BrowserMessageFilter { public: @@ -1592,6 +1593,11 @@ // Waits for the next viz::LocalSurfaceId be received and returns it. viz::LocalSurfaceId WaitForSurfaceId(); + bool pinch_gesture_active_set() { return pinch_gesture_active_set_; } + bool pinch_gesture_active_cleared() { return pinch_gesture_active_cleared_; } + + void WaitForPinchGestureEnd(); + protected: ~SynchronizeVisualPropertiesMessageFilter() override; @@ -1623,6 +1629,11 @@ viz::LocalSurfaceId last_surface_id_; std::unique_ptr<base::RunLoop> surface_id_run_loop_; + bool pinch_gesture_active_set_; + bool pinch_gesture_active_cleared_; + bool last_pinch_gesture_active_; + std::unique_ptr<base::RunLoop> pinch_end_run_loop_; + DISALLOW_COPY_AND_ASSIGN(SynchronizeVisualPropertiesMessageFilter); };
diff --git a/content/renderer/compositor/layer_tree_view.cc b/content/renderer/compositor/layer_tree_view.cc index 5f163f8..6d7e1f34 100644 --- a/content/renderer/compositor/layer_tree_view.cc +++ b/content/renderer/compositor/layer_tree_view.cc
@@ -425,8 +425,11 @@ layer_tree_host_->SetRasterColorSpace(color_space); } -void LayerTreeView::SetExternalPageScaleFactor(float page_scale_factor) { - layer_tree_host_->SetExternalPageScaleFactor(page_scale_factor); +void LayerTreeView::SetExternalPageScaleFactor( + float page_scale_factor, + bool is_external_pinch_gesture_active) { + layer_tree_host_->SetExternalPageScaleFactor( + page_scale_factor, is_external_pinch_gesture_active); } void LayerTreeView::ClearCachesOnNextCommit() {
diff --git a/content/renderer/compositor/layer_tree_view.h b/content/renderer/compositor/layer_tree_view.h index 7b0aac53..a477847 100644 --- a/content/renderer/compositor/layer_tree_view.h +++ b/content/renderer/compositor/layer_tree_view.h
@@ -107,7 +107,8 @@ bool SendMessageToMicroBenchmark(int id, std::unique_ptr<base::Value> value); void SetFrameSinkId(const viz::FrameSinkId& frame_sink_id); void SetRasterColorSpace(const gfx::ColorSpace& color_space); - void SetExternalPageScaleFactor(float page_scale_factor); + void SetExternalPageScaleFactor(float page_scale_factor, + bool is_external_pinch_gesture_active); void ClearCachesOnNextCommit(); void SetContentSourceId(uint32_t source_id); void SetViewportSizeAndScale(
diff --git a/content/renderer/render_frame_proxy.cc b/content/renderer/render_frame_proxy.cc index d4e8c3f0..5342a18b 100644 --- a/content/renderer/render_frame_proxy.cc +++ b/content/renderer/render_frame_proxy.cc
@@ -311,8 +311,10 @@ SynchronizeVisualProperties(); } -void RenderFrameProxy::OnPageScaleFactorChanged(float page_scale_factor) { +void RenderFrameProxy::OnPageScaleFactorChanged(float page_scale_factor, + bool is_pinch_gesture_active) { pending_visual_properties_.page_scale_factor = page_scale_factor; + pending_visual_properties_.is_pinch_gesture_active = is_pinch_gesture_active; SynchronizeVisualProperties(); } @@ -687,6 +689,8 @@ pending_visual_properties_.zoom_level || sent_visual_properties_->page_scale_factor != pending_visual_properties_.page_scale_factor || + sent_visual_properties_->is_pinch_gesture_active != + pending_visual_properties_.is_pinch_gesture_active || capture_sequence_number_changed; if (synchronized_props_changed) {
diff --git a/content/renderer/render_frame_proxy.h b/content/renderer/render_frame_proxy.h index 947c70a..bebf7d1 100644 --- a/content/renderer/render_frame_proxy.h +++ b/content/renderer/render_frame_proxy.h
@@ -145,8 +145,9 @@ void OnZoomLevelChanged(double zoom_level); // Out-of-process child frames receive a signal from RenderWidget when the - // page scale factor has changed. - void OnPageScaleFactorChanged(float page_scale_factor); + // page scale factor has changed, and/or a pinch-zoom gesture starts/ends. + void OnPageScaleFactorChanged(float page_scale_factor, + bool is_pinch_gesture_active); // Invoked by RenderWidget when a new capture sequence number was set, // indicating that surfaces should be synchronized. @@ -229,6 +230,10 @@ void WasEvicted(); + bool is_pinch_gesture_active_for_testing() { + return pending_visual_properties_.is_pinch_gesture_active; + } + private: RenderFrameProxy(int routing_id);
diff --git a/content/renderer/render_view_browsertest.cc b/content/renderer/render_view_browsertest.cc index e60f863..3bb88dc9 100644 --- a/content/renderer/render_view_browsertest.cc +++ b/content/renderer/render_view_browsertest.cc
@@ -548,6 +548,54 @@ } }; +TEST_F(RenderViewImplTest, IsPinchGestureActivePropagatesToProxies) { + LoadHTML( + "<body style='min-height:1000px;'>" + " <iframe src='data:text/html,frame 1'></iframe>" + " <iframe src='data:text/html,frame 2'></iframe>" + "</body>"); + + // Verify child's proxy doesn't think we're pinching. + blink::WebFrame* root_web_frame = frame()->GetWebFrame(); + ASSERT_TRUE(root_web_frame->FirstChild()->IsWebLocalFrame()); + TestRenderFrame* child_frame_1 = + static_cast<TestRenderFrame*>(RenderFrame::FromWebFrame( + root_web_frame->FirstChild()->ToWebLocalFrame())); + ASSERT_TRUE(child_frame_1); + TestRenderFrame* child_frame_2 = + static_cast<TestRenderFrame*>(RenderFrame::FromWebFrame( + root_web_frame->FirstChild()->NextSibling()->ToWebLocalFrame())); + ASSERT_TRUE(child_frame_2); + child_frame_1->SwapOut(kProxyRoutingId, true, + ReconstructReplicationStateForTesting(child_frame_1)); + EXPECT_TRUE(root_web_frame->FirstChild()->IsWebRemoteFrame()); + RenderFrameProxy* child_proxy_1 = RenderFrameProxy::FromWebFrame( + root_web_frame->FirstChild()->ToWebRemoteFrame()); + ASSERT_TRUE(child_proxy_1); + EXPECT_FALSE(child_proxy_1->is_pinch_gesture_active_for_testing()); + + // Set the |is_pinch_gesture_active| flag. + view()->PageScaleFactorChanged(1.f, true); + EXPECT_TRUE(child_proxy_1->is_pinch_gesture_active_for_testing()); + + // Create a new remote child, and get its proxy. Swapping out will force + // creation and registering of a new RenderFrameProxy, which should pick up + // the existing setting. + child_frame_2->SwapOut(kProxyRoutingId + 1, true, + ReconstructReplicationStateForTesting(child_frame_2)); + EXPECT_TRUE(root_web_frame->FirstChild()->NextSibling()->IsWebRemoteFrame()); + RenderFrameProxy* child_proxy_2 = RenderFrameProxy::FromWebFrame( + root_web_frame->FirstChild()->NextSibling()->ToWebRemoteFrame()); + + // Verify new child has the flag too. + EXPECT_TRUE(child_proxy_2->is_pinch_gesture_active_for_testing()); + + // Reset the flag, make sure both children respond. + view()->PageScaleFactorChanged(1.f, false); + EXPECT_FALSE(child_proxy_1->is_pinch_gesture_active_for_testing()); + EXPECT_FALSE(child_proxy_2->is_pinch_gesture_active_for_testing()); +} + // Test that we get form state change notifications when input fields change. TEST_F(RenderViewImplTest, OnNavStateChanged) { view()->set_send_content_state_immediately(true); @@ -877,10 +925,6 @@ // continues to receive the original ScreenInfo and not the emualted // ScreenInfo. TEST_F(RenderViewImplScaleFactorTest, DeviceEmulationWithOOPIF) { - // This test should only run with --site-per-process. - if (!AreAllSitesIsolatedForTesting()) - return; - const float device_scale = 2.0f; float compositor_dsf = compositor_deps_->IsUseZoomForDSFEnabled() ? 1.f : device_scale; @@ -930,11 +974,6 @@ // Verify that security origins are replicated properly to RenderFrameProxies // when swapping out. TEST_F(RenderViewImplTest, OriginReplicationForSwapOut) { - // This test should only run with --site-per-process, since origin - // replication only happens in that mode. - if (!AreAllSitesIsolatedForTesting()) - return; - LoadHTML( "Hello <iframe src='data:text/html,frame 1'></iframe>" "<iframe src='data:text/html,frame 2'></iframe>"); @@ -1046,10 +1085,6 @@ // destroyed along with the proxy. This protects against races in // https://crbug.com/526304 and https://crbug.com/568676. TEST_F(RenderViewImplTest, DetachingProxyAlsoDestroysProvisionalFrame) { - // This test should only run with --site-per-process. - if (!AreAllSitesIsolatedForTesting()) - return; - LoadHTML("Hello <iframe src='data:text/html,frame 1'></iframe>"); WebFrame* web_frame = frame()->GetWebFrame(); TestRenderFrame* child_frame = static_cast<TestRenderFrame*>(
diff --git a/content/renderer/render_widget.cc b/content/renderer/render_widget.cc index 9fb5ae6..cd7cccd 100644 --- a/content/renderer/render_widget.cc +++ b/content/renderer/render_widget.cc
@@ -860,10 +860,18 @@ // the visual properties here. While blink doesn't need to know this // page scale factor outside the main frame, the compositor does in // order to produce its output at the correct scale. - layer_tree_view_->SetExternalPageScaleFactor(params.page_scale_factor); + layer_tree_view_->SetExternalPageScaleFactor( + params.page_scale_factor, params.is_pinch_gesture_active); // Store the value to give to any new RenderFrameProxy that is // registered. page_scale_factor_from_mainframe_ = params.page_scale_factor; + // Similarly, only the main frame knows when a pinch gesture is active, + // but this information is needed in subframes so they can throttle + // re-rastering in the same manner as the main frame. + // |is_pinch_gesture_active| follows the same path to the subframe + // compositor(s) as |page_scale_factor|. + is_pinch_gesture_active_from_mainframe_ = + params.is_pinch_gesture_active; // Push the page scale factor down to any child RenderWidgets via our // child proxy frames. // TODO(danakj): This ends up setting the page scale factor in the @@ -872,8 +880,10 @@ // global value per-page, we could instead store it once in the browser // (such as in RenderViewHost) and distribute it to each frame-hosted // RenderWidget from there. - for (auto& child_proxy : render_frame_proxies_) - child_proxy.OnPageScaleFactorChanged(params.page_scale_factor); + for (auto& child_proxy : render_frame_proxies_) { + child_proxy.OnPageScaleFactorChanged(params.page_scale_factor, + params.is_pinch_gesture_active); + } } gfx::Size old_visible_viewport_size = visible_viewport_size_; @@ -3440,7 +3450,8 @@ // frame trees). A new RenderFrameProxy means there is a new child // RenderWidget in another frame tree. In order for it to hear about // the page scale factor we pass along the last seen value here. - proxy->OnPageScaleFactorChanged(page_scale_factor_from_mainframe_); + proxy->OnPageScaleFactorChanged(page_scale_factor_from_mainframe_, + is_pinch_gesture_active_from_mainframe_); } void RenderWidget::UnregisterRenderFrameProxy(RenderFrameProxy* proxy) { @@ -3587,21 +3598,16 @@ // of which will be via proxy child frame). These will each in turn forward // the message to their child RenderWidgets (through their proxy child // frames). - // TODO(crbug.com/924336): This value is continuously propagated during a - // pinch-zoom, causing the child RenderWidgets to re-raster, while the main - // frame is able to throttle re-raster to powers of 2. We could find some way - // to throttle child RenderWidgets also, perhaps by informing them when the - // pinch-zoom gesture is started and stopped. DCHECK(!is_frozen_); DCHECK(delegate()); - // TODO(wjmaclean): In the next CL, plumb |is_pinch_gesture_active| into the - // observer via observer.OnPageScaleFactorChanged() and allow it to trigger - // SynchronizeVisualProperties if needed. - for (auto& observer : render_frame_proxies_) - observer.OnPageScaleFactorChanged(page_scale_factor); + for (auto& observer : render_frame_proxies_) { + observer.OnPageScaleFactorChanged(page_scale_factor, + is_pinch_gesture_active); + } // Store the value to give to any new RenderFrameProxy that is registered. page_scale_factor_from_mainframe_ = page_scale_factor; + is_pinch_gesture_active_from_mainframe_ = is_pinch_gesture_active; } void RenderWidget::UseSynchronousResizeModeForTesting(bool enable) {
diff --git a/content/renderer/render_widget.h b/content/renderer/render_widget.h index d0fd4036..a289a6a 100644 --- a/content/renderer/render_widget.h +++ b/content/renderer/render_widget.h
@@ -1136,10 +1136,11 @@ // The height of the browser bottom controls. float bottom_controls_height_ = 0.f; - // The last seen page scale factor, which comes from the main frame and is - // propagated through the RenderWidget tree. This value is passed to any new + // The last seen page scale state, which comes from the main frame and is + // propagated through the RenderWidget tree. This state is passed to any new // child RenderWidget. float page_scale_factor_from_mainframe_ = 1.f; + bool is_pinch_gesture_active_from_mainframe_ = false; // This is initialized to zero and is incremented on each non-same-page // navigation commit by RenderFrameImpl. At that time it is sent to the
diff --git a/content/renderer/render_widget_unittest.cc b/content/renderer/render_widget_unittest.cc index 023f4ede..e25ab23 100644 --- a/content/renderer/render_widget_unittest.cc +++ b/content/renderer/render_widget_unittest.cc
@@ -15,11 +15,13 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/scoped_task_environment.h" +#include "base/unguessable_token.h" #include "build/build_config.h" #include "cc/layers/solid_color_layer.h" #include "cc/trees/layer_tree_host.h" #include "components/viz/common/features.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" +#include "content/common/frame_replication_state.h" #include "content/common/input/input_handler.mojom.h" #include "content/common/input/synthetic_web_input_event_builders.h" #include "content/common/input_messages.h" @@ -31,6 +33,7 @@ #include "content/renderer/compositor/layer_tree_view.h" #include "content/renderer/devtools/render_widget_screen_metrics_emulator.h" #include "content/renderer/input/widget_input_handler_manager.h" +#include "content/renderer/render_frame_proxy.h" #include "content/renderer/render_widget_delegate.h" #include "content/test/fake_compositor_dependencies.h" #include "content/test/mock_render_process.h" @@ -551,6 +554,41 @@ const blink::WebDeviceEmulationParams& params) override {} }; +// Tests that the value of VisualProperties::is_pinch_gesture_active is +// propagated to the LayerTreeHost when properties are synced, but only for +// subframe widgets. +TEST_F(RenderWidgetUnittest, ActivePinchGestureUpdatesLayerTreeHost) { + auto* layer_tree_host = widget()->layer_tree_view()->layer_tree_host(); + EXPECT_FALSE(layer_tree_host->is_external_pinch_gesture_active_for_testing()); + content::VisualProperties visual_properties; + + // Sync visual properties on a child RenderWidget. + visual_properties.is_pinch_gesture_active = true; + widget()->OnSynchronizeVisualProperties(visual_properties); + // We expect the |is_pinch_gesture_active| value to propagate to the + // LayerTreeHost for sub-frames. Since GesturePinch events are handled + // directly in the main-frame's layer tree (and only there), information about + // whether or not we're in a pinch gesture must be communicated separately to + // sub-frame layer trees, via SynchronizeVisualProperties. This information + // is required to allow sub-frame compositors to throttle rastering while + // pinch gestures are active. + EXPECT_TRUE(layer_tree_host->is_external_pinch_gesture_active_for_testing()); + visual_properties.is_pinch_gesture_active = false; + widget()->OnSynchronizeVisualProperties(visual_properties); + EXPECT_FALSE(layer_tree_host->is_external_pinch_gesture_active_for_testing()); + + // Repeat with a 'mainframe' widget. + widget()->set_delegate(std::make_unique<StubRenderWidgetDelegate>()); + visual_properties.is_pinch_gesture_active = true; + widget()->OnSynchronizeVisualProperties(visual_properties); + // We do not expect the |is_pinch_gesture_active| value to propagate to the + // LayerTreeHost for the main-frame. Since GesturePinch events are handled + // directly by the layer tree for the main frame, it already knows whether or + // not a pinch gesture is active, and so we shouldn't propagate this + // information to the layer tree for a main-frame's widget. + EXPECT_FALSE(layer_tree_host->is_external_pinch_gesture_active_for_testing()); +} + TEST_F(RenderWidgetPopupUnittest, EmulatingPopupRect) { blink::WebRect popup_screen_rect(200, 250, 100, 400); widget()->SetWindowRect(popup_screen_rect);
diff --git a/content/test/BUILD.gn b/content/test/BUILD.gn index 32aeb0d2..3eb36ce 100644 --- a/content/test/BUILD.gn +++ b/content/test/BUILD.gn
@@ -1818,7 +1818,6 @@ "../renderer/media/stream/mock_media_stream_video_source.h", "../renderer/media/stream/processed_local_audio_source_unittest.cc", "../renderer/media/stream/user_media_client_impl_unittest.cc", - "../renderer/media/stream/video_track_adapter_unittest.cc", "../renderer/media/stream/webmediaplayer_ms_unittest.cc", "../renderer/media/video_capture/video_capture_impl_manager_unittest.cc", "../renderer/media/video_capture/video_capture_impl_unittest.cc",
diff --git a/device/fido/get_assertion_handler_unittest.cc b/device/fido/get_assertion_handler_unittest.cc index 47bb533b..91766cb 100644 --- a/device/fido/get_assertion_handler_unittest.cc +++ b/device/fido/get_assertion_handler_unittest.cc
@@ -25,6 +25,7 @@ #include "device/fido/hid/fake_hid_impl_for_testing.h" #include "device/fido/make_credential_task.h" #include "device/fido/mock_fido_device.h" +#include "device/fido/scoped_virtual_fido_device.h" #include "device/fido/test_callback_receiver.h" #include "device/fido/u2f_command_constructor.h" #include "testing/gmock/include/gmock/gmock.h" @@ -84,6 +85,8 @@ bool controls_dispatch_ = false; }; +// FidoGetAssertionHandlerTest allows testing GetAssertionRequestHandler against +// MockFidoDevices injected via a ScopedFakeFidoDiscoveryFactory. class FidoGetAssertionHandlerTest : public ::testing::Test { public: FidoGetAssertionHandlerTest() { @@ -649,42 +652,6 @@ ::testing::UnorderedElementsAre(FidoTransportProtocol::kInternal)); } -// Tests a scenario where authenticator of incorrect transport type was used to -// conduct CTAP GetAssertion call. -// -// TODO(engedy): This should not happen, instead |allowCredentials| should be -// filtered to only contain items compatible with the transport actually used to -// talk to the authenticator. -TEST_F(FidoGetAssertionHandlerTest, IncorrectTransportType) { - // GetAssertion request that expects GetAssertion call for credential - // |CredentialType::kPublicKey| to be signed with Cable authenticator. - auto request = CreateTestRequestWithCableExtension(); - request.SetAllowList({ - {CredentialType::kPublicKey, - fido_parsing_utils::Materialize( - test_data::kTestGetAssertionCredentialId), - {FidoTransportProtocol::kBluetoothLowEnergy}}, - {CredentialType::kPublicKey, - fido_parsing_utils::Materialize(kBogusCredentialId), - {FidoTransportProtocol::kUsbHumanInterfaceDevice}}, - }); - auto request_handler = - CreateGetAssertionHandlerWithRequest(std::move(request)); - discovery()->WaitForCallToStartAndSimulateSuccess(); - auto device = MockFidoDevice::MakeCtapWithGetInfoExpectation(); - // Since transport type of |device| is different from what the relying party - // defined in |request| above, this request should fail. - device->SetDeviceTransport(FidoTransportProtocol::kUsbHumanInterfaceDevice); - device->ExpectCtap2CommandAndRespondWith( - CtapRequestCommand::kAuthenticatorGetAssertion, - test_data::kTestGetAssertionResponse); - - discovery()->AddDevice(std::move(device)); - - scoped_task_environment_.FastForwardUntilNoTasksRemain(); - EXPECT_FALSE(get_assertion_callback().was_called()); -} - // If a device with transport type kInternal returns a // CTAP2_ERR_OPERATION_DENIED error, the request should complete with // FidoReturnCode::kUserConsentDenied. Pending authenticators should be @@ -734,6 +701,43 @@ get_assertion_callback().status()); } +// Tests a scenario where authenticator of incorrect transport type was used to +// conduct CTAP GetAssertion call. +// +// TODO(engedy): This should not happen, instead |allowCredentials| should be +// filtered to only contain items compatible with the transport actually used to +// talk to the authenticator. +TEST(GetAssertionRequestHandlerTest, IncorrectTransportType) { + base::test::ScopedTaskEnvironment scoped_task_environment{ + base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME}; + device::test::ScopedVirtualFidoDevice virtual_device; + virtual_device.SetSupportedProtocol(device::ProtocolVersion::kCtap); + ASSERT_TRUE(virtual_device.mutable_state()->InjectRegistration( + fido_parsing_utils::Materialize(test_data::kTestGetAssertionCredentialId), + test_data::kRelyingPartyId)); + + // Request the correct credential ID, but set a different transport hint. + CtapGetAssertionRequest request(test_data::kRelyingPartyId, + test_data::kClientDataJson); + request.SetAllowList({ + {CredentialType::kPublicKey, + fido_parsing_utils::Materialize( + test_data::kTestGetAssertionCredentialId), + {FidoTransportProtocol::kBluetoothLowEnergy}}, + }); + + TestGetAssertionRequestCallback cb; + auto request_handler = std::make_unique<GetAssertionRequestHandler>( + nullptr /* connector */, + base::flat_set<FidoTransportProtocol>( + {FidoTransportProtocol::kUsbHumanInterfaceDevice}), + std::move(request), cb.callback()); + request_handler->SetPlatformAuthenticatorOrMarkUnavailable(base::nullopt); + + scoped_task_environment.FastForwardUntilNoTasksRemain(); + EXPECT_FALSE(cb.was_called()); +} + #if defined(OS_WIN) // Verify that the request handler instantiates a HID device backed // FidoDeviceAuthenticator or a WinNativeCrossPlatformAuthenticator, depending
diff --git a/device/fido/get_assertion_task.cc b/device/fido/get_assertion_task.cc index 2eb337fe..013f181 100644 --- a/device/fido/get_assertion_task.cc +++ b/device/fido/get_assertion_task.cc
@@ -57,23 +57,28 @@ } } -void GetAssertionTask::GetAssertion() { - // If appId extension was used in the request and device is a hybrid U2F/CTAP2 - // device, then first issue a silent GetAssertionRequest. If no credentials in - // allowed credential list are recognized, it's possible that the credential - // is registered via U2F. Under these circumstances, the request should be - // issued via the U2F protocol. Otherwise, proceed with a normal GetAssertion - // request. - if (MayFallbackToU2fWithAppIdExtension(*device(), request_)) { - request_.SetUserPresenceRequired(false); - const auto original_uv_configuration = request_.user_verification(); - request_.SetUserVerification(UserVerificationRequirement::kDiscouraged); +CtapGetAssertionRequest GetAssertionTask::NextSilentRequest() { + DCHECK(request_.allow_list() && + current_credential_ < request_.allow_list()->size()); + CtapGetAssertionRequest request = request_; + request.SetAllowList({{request_.allow_list()->at(current_credential_)}}); + request.SetUserPresenceRequired(false); + request.SetUserVerification(UserVerificationRequirement::kDiscouraged); + return request; +} +void GetAssertionTask::GetAssertion() { + // Silently probe each credential in the allow list to work around + // authenticators rejecting lists over a certain size. Also probe silently if + // the request may fall back to U2F and the authenticator doesn't recognize + // any of the provided credential IDs. + if ((request_.allow_list() && request_.allow_list()->size() > 1) || + MayFallbackToU2fWithAppIdExtension(*device(), request_)) { sign_operation_ = std::make_unique<Ctap2DeviceOperation< CtapGetAssertionRequest, AuthenticatorGetAssertionResponse>>( - device(), request_, + device(), NextSilentRequest(), base::BindOnce(&GetAssertionTask::HandleResponseToSilentRequest, - weak_factory_.GetWeakPtr(), original_uv_configuration), + weak_factory_.GetWeakPtr()), base::BindOnce(&ReadCTAPGetAssertionResponse)); sign_operation_->Start(); return; @@ -120,39 +125,55 @@ } void GetAssertionTask::HandleResponseToSilentRequest( - UserVerificationRequirement original_uv_configuration, CtapDeviceResponseCode response_code, base::Optional<AuthenticatorGetAssertionResponse> response_data) { - DCHECK(!request_.user_presence_required()); - request_.SetUserPresenceRequired(true); + DCHECK(request_.allow_list() && request_.allow_list()->size() > 0); - if (response_code != CtapDeviceResponseCode::kSuccess) { - // An error occurred or no credentials in the allowed list were recognized. - // However, as the relying party has provided appId extension, try again - // with U2F in case that works. - DCHECK(MayFallbackToU2fWithAppIdExtension(*device(), request_)); + // Credential was recognized by the device. As this authentication was a + // silent authentication (i.e. user touch was not provided), try again with + // only the matching credential, user presence enforced and with the original + // user verification configuration. + if (response_code == CtapDeviceResponseCode::kSuccess) { + CtapGetAssertionRequest request = request_; + request.SetAllowList({{request_.allow_list()->at(current_credential_)}}); + sign_operation_ = std::make_unique<Ctap2DeviceOperation< + CtapGetAssertionRequest, AuthenticatorGetAssertionResponse>>( + device(), std::move(request), + base::BindOnce(&GetAssertionTask::HandleResponse, + weak_factory_.GetWeakPtr()), + base::BindOnce(&ReadCTAPGetAssertionResponse)); + sign_operation_->Start(); + return; + } + + // Credential was not recognized or an error occurred. Probe the next + // credential. + if (++current_credential_ < request_.allow_list()->size()) { + sign_operation_ = std::make_unique<Ctap2DeviceOperation< + CtapGetAssertionRequest, AuthenticatorGetAssertionResponse>>( + device(), NextSilentRequest(), + base::BindOnce(&GetAssertionTask::HandleResponseToSilentRequest, + weak_factory_.GetWeakPtr()), + base::BindOnce(&ReadCTAPGetAssertionResponse)); + sign_operation_->Start(); + return; + } + + // None of the credentials were recognized. Fall back to U2F or collect a + // dummy touch. + if (MayFallbackToU2fWithAppIdExtension(*device(), request_)) { device()->set_supported_protocol(ProtocolVersion::kU2f); U2fSign(); return; } - - // Credential was recognized by the device. As this authentication was a - // silent authentication (i.e. user touch was not provided), try again with - // user presence enforced and with the original user verification - // configuration. - DCHECK_EQ(UserVerificationRequirement::kDiscouraged, - request_.user_verification()); - DCHECK_EQ(ProtocolVersion::kCtap, device()->supported_protocol()); - request_.SetUserVerification(original_uv_configuration); - - sign_operation_ = - std::make_unique<Ctap2DeviceOperation<CtapGetAssertionRequest, - AuthenticatorGetAssertionResponse>>( - device(), request_, - base::BindOnce(&GetAssertionTask::HandleResponse, - weak_factory_.GetWeakPtr()), - base::BindOnce(&ReadCTAPGetAssertionResponse)); - sign_operation_->Start(); + dummy_register_operation_ = std::make_unique<Ctap2DeviceOperation< + CtapMakeCredentialRequest, AuthenticatorMakeCredentialResponse>>( + device(), MakeCredentialTask::GetTouchRequest(device()), + base::BindOnce(&GetAssertionTask::HandleDummyMakeCredentialComplete, + weak_factory_.GetWeakPtr()), + base::BindOnce(&ReadCTAPMakeCredentialResponse, + device()->DeviceTransport())); + dummy_register_operation_->Start(); } void GetAssertionTask::HandleDummyMakeCredentialComplete(
diff --git a/device/fido/get_assertion_task.h b/device/fido/get_assertion_task.h index 87e29f4..96d3e3e 100644 --- a/device/fido/get_assertion_task.h +++ b/device/fido/get_assertion_task.h
@@ -51,6 +51,8 @@ void GetAssertion(); void U2fSign(); + CtapGetAssertionRequest NextSilentRequest(); + // HandleResponse is the callback to a CTAP2 assertion request that requested // user-presence. void HandleResponse( @@ -58,10 +60,8 @@ base::Optional<AuthenticatorGetAssertionResponse> response_data); // HandleResponseToSilentRequest is a callback to a request without user- - // presence requested used when this assertion request may require falling - // back to U2F. + // presence requested used to silently probe credentials from the allow list. void HandleResponseToSilentRequest( - UserVerificationRequirement original_uv_configuration, CtapDeviceResponseCode response_code, base::Optional<AuthenticatorGetAssertionResponse> response_data); @@ -75,6 +75,8 @@ std::unique_ptr<SignOperation> sign_operation_; std::unique_ptr<RegisterOperation> dummy_register_operation_; GetAssertionTaskCallback callback_; + size_t current_credential_ = 0; + base::WeakPtrFactory<GetAssertionTask> weak_factory_; DISALLOW_COPY_AND_ASSIGN(GetAssertionTask);
diff --git a/device/fido/make_credential_task.cc b/device/fido/make_credential_task.cc index d1e901e..26b857c 100644 --- a/device/fido/make_credential_task.cc +++ b/device/fido/make_credential_task.cc
@@ -42,17 +42,16 @@ } // namespace -MakeCredentialTask::MakeCredentialTask( - FidoDevice* device, - CtapMakeCredentialRequest request_parameter, - MakeCredentialTaskCallback callback) +MakeCredentialTask::MakeCredentialTask(FidoDevice* device, + CtapMakeCredentialRequest request, + MakeCredentialTaskCallback callback) : FidoTask(device), - request_parameter_(std::move(request_parameter)), + request_(std::move(request)), callback_(std::move(callback)), weak_factory_(this) { // The UV parameter should have been made binary by this point because CTAP2 // only takes a binary value. - DCHECK_NE(request_parameter_.user_verification(), + DCHECK_NE(request_.user_verification(), UserVerificationRequirement::kPreferred); } @@ -98,8 +97,8 @@ void MakeCredentialTask::StartTask() { if (device()->supported_protocol() == ProtocolVersion::kCtap && - !request_parameter_.is_u2f_only() && - !ShouldUseU2fBecauseCtapRequiresClientPin(device(), request_parameter_)) { + !request_.is_u2f_only() && + !ShouldUseU2fBecauseCtapRequiresClientPin(device(), request_)) { MakeCredential(); } else { // |device_info| should be present iff the device is CTAP2. This will be @@ -112,17 +111,112 @@ } } +CtapGetAssertionRequest MakeCredentialTask::NextSilentSignRequest() { + DCHECK(request_.exclude_list() && + current_credential_ < request_.exclude_list()->size()); + CtapGetAssertionRequest request(request_.rp().rp_id(), + /*client_data_json=*/""); + request.SetAllowList({{request_.exclude_list()->at(current_credential_)}}); + request.SetUserPresenceRequired(false); + request.SetUserVerification(UserVerificationRequirement::kDiscouraged); + return request; +} + void MakeCredentialTask::MakeCredential() { + // Silently probe each credential in the allow list to work around + // authenticators rejecting lists over a certain size. + if (request_.exclude_list() && request_.exclude_list()->size() > 1) { + silent_sign_operation_ = std::make_unique<Ctap2DeviceOperation< + CtapGetAssertionRequest, AuthenticatorGetAssertionResponse>>( + device(), NextSilentSignRequest(), + base::BindOnce(&MakeCredentialTask::HandleResponseToSilentSignRequest, + weak_factory_.GetWeakPtr()), + base::BindOnce(&ReadCTAPGetAssertionResponse)); + silent_sign_operation_->Start(); + return; + } + register_operation_ = std::make_unique<Ctap2DeviceOperation< CtapMakeCredentialRequest, AuthenticatorMakeCredentialResponse>>( - device(), std::move(request_parameter_), std::move(callback_), + device(), std::move(request_), std::move(callback_), base::BindOnce(&ReadCTAPMakeCredentialResponse, device()->DeviceTransport())); register_operation_->Start(); } +void MakeCredentialTask::HandleResponseToSilentSignRequest( + CtapDeviceResponseCode response_code, + base::Optional<AuthenticatorGetAssertionResponse> response_data) { + DCHECK(request_.exclude_list() && request_.exclude_list()->size() > 0); + + // The authenticator recognized a credential from the exclude list. Send the + // actual request with only that credential in the exclude list to collect a + // touch and and the CTAP2_ERR_CREDENTIAL_EXCLUDED error code. + if (response_code == CtapDeviceResponseCode::kSuccess) { + CtapMakeCredentialRequest request = request_; + request.SetExcludeList( + {{request_.exclude_list()->at(current_credential_)}}); + register_operation_ = std::make_unique<Ctap2DeviceOperation< + CtapMakeCredentialRequest, AuthenticatorMakeCredentialResponse>>( + device(), std::move(request), std::move(callback_), + base::BindOnce(&ReadCTAPMakeCredentialResponse, + device()->DeviceTransport())); + register_operation_->Start(); + return; + } + + // The authenticator returned an unexpected error. Collect a touch to take the + // authenticator out of the set of active devices. + if (response_code != CtapDeviceResponseCode::kCtap2ErrInvalidCredential && + response_code != CtapDeviceResponseCode::kCtap2ErrNoCredentials && + response_code != CtapDeviceResponseCode::kCtap2ErrLimitExceeded && + response_code != CtapDeviceResponseCode::kCtap2ErrRequestTooLarge) { + register_operation_ = std::make_unique<Ctap2DeviceOperation< + CtapMakeCredentialRequest, AuthenticatorMakeCredentialResponse>>( + device(), GetTouchRequest(device()), + base::BindOnce(&MakeCredentialTask::HandleResponseToDummyTouch, + weak_factory_.GetWeakPtr()), + base::BindOnce(&ReadCTAPMakeCredentialResponse, + device()->DeviceTransport())); + register_operation_->Start(); + return; + } + + // The authenticator doesn't recognize this particular credential from the + // exclude list. Try the next one. + if (++current_credential_ < request_.exclude_list()->size()) { + silent_sign_operation_ = std::make_unique<Ctap2DeviceOperation< + CtapGetAssertionRequest, AuthenticatorGetAssertionResponse>>( + device(), NextSilentSignRequest(), + base::BindOnce(&MakeCredentialTask::HandleResponseToSilentSignRequest, + weak_factory_.GetWeakPtr()), + base::BindOnce(&ReadCTAPGetAssertionResponse)); + silent_sign_operation_->Start(); + return; + } + + // None of the credentials from the exclude list were recognized. The actual + // register request may proceed but without the exclude list present in case + // it exceeds the device's size limit. + CtapMakeCredentialRequest request = request_; + request.SetExcludeList({}); + register_operation_ = std::make_unique<Ctap2DeviceOperation< + CtapMakeCredentialRequest, AuthenticatorMakeCredentialResponse>>( + device(), std::move(request), std::move(callback_), + base::BindOnce(&ReadCTAPMakeCredentialResponse, + device()->DeviceTransport())); + register_operation_->Start(); +} + +void MakeCredentialTask::HandleResponseToDummyTouch( + CtapDeviceResponseCode response_code, + base::Optional<AuthenticatorMakeCredentialResponse> response_data) { + std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, + base::nullopt); +} + void MakeCredentialTask::U2fRegister() { - if (!IsConvertibleToU2fRegisterCommand(request_parameter_)) { + if (!IsConvertibleToU2fRegisterCommand(request_)) { std::move(callback_).Run(CtapDeviceResponseCode::kCtap2ErrOther, base::nullopt); return; @@ -130,7 +224,7 @@ DCHECK_EQ(ProtocolVersion::kU2f, device()->supported_protocol()); register_operation_ = std::make_unique<U2fRegisterOperation>( - device(), std::move(request_parameter_), + device(), std::move(request_), base::BindOnce(&MakeCredentialTask::MaybeRevertU2fFallback, weak_factory_.GetWeakPtr())); register_operation_->Start();
diff --git a/device/fido/make_credential_task.h b/device/fido/make_credential_task.h index 0b3c922..beda0d5 100644 --- a/device/fido/make_credential_task.h +++ b/device/fido/make_credential_task.h
@@ -15,7 +15,9 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/optional.h" +#include "device/fido/authenticator_get_assertion_response.h" #include "device/fido/authenticator_make_credential_response.h" +#include "device/fido/ctap_get_assertion_request.h" #include "device/fido/ctap_make_credential_request.h" #include "device/fido/device_operation.h" #include "device/fido/fido_constants.h" @@ -30,12 +32,14 @@ using MakeCredentialTaskCallback = base::OnceCallback<void( CtapDeviceResponseCode, base::Optional<AuthenticatorMakeCredentialResponse>)>; + using SignOperation = DeviceOperation<CtapGetAssertionRequest, + AuthenticatorGetAssertionResponse>; using RegisterOperation = DeviceOperation<CtapMakeCredentialRequest, AuthenticatorMakeCredentialResponse>; MakeCredentialTask(FidoDevice* device, - CtapMakeCredentialRequest request_parameter, + CtapMakeCredentialRequest request, MakeCredentialTaskCallback callback); ~MakeCredentialTask() override; @@ -48,14 +52,25 @@ void StartTask() final; void MakeCredential(); + CtapGetAssertionRequest NextSilentSignRequest(); + void HandleResponseToSilentSignRequest( + CtapDeviceResponseCode response_code, + base::Optional<AuthenticatorGetAssertionResponse> response_data); + void HandleResponseToDummyTouch( + CtapDeviceResponseCode response_code, + base::Optional<AuthenticatorMakeCredentialResponse> response_data); + void U2fRegister(); void MaybeRevertU2fFallback( CtapDeviceResponseCode status, base::Optional<AuthenticatorMakeCredentialResponse> response); - CtapMakeCredentialRequest request_parameter_; + CtapMakeCredentialRequest request_; std::unique_ptr<RegisterOperation> register_operation_; + std::unique_ptr<SignOperation> silent_sign_operation_; MakeCredentialTaskCallback callback_; + size_t current_credential_ = 0; + base::WeakPtrFactory<MakeCredentialTask> weak_factory_; DISALLOW_COPY_AND_ASSIGN(MakeCredentialTask);
diff --git a/device/fido/virtual_ctap2_device.cc b/device/fido/virtual_ctap2_device.cc index 162b79a..cee3f30 100644 --- a/device/fido/virtual_ctap2_device.cc +++ b/device/fido/virtual_ctap2_device.cc
@@ -552,6 +552,11 @@ const auto rp_id_hash = fido_parsing_utils::CreateSHA256Hash(request.rp().rp_id()); if (request.exclude_list()) { + if (config_.reject_large_allow_and_exclude_lists && + request.exclude_list()->size() > 1) { + return CtapDeviceResponseCode::kCtap2ErrLimitExceeded; + } + for (const auto& excluded_credential : *request.exclude_list()) { if (FindRegistrationData(excluded_credential.id(), rp_id_hash)) { if (mutable_state()->simulate_press_callback) { @@ -699,6 +704,11 @@ found_registrations; if (request.allow_list()) { + if (config_.reject_large_allow_and_exclude_lists && + request.allow_list()->size() > 1) { + return CtapDeviceResponseCode::kCtap2ErrLimitExceeded; + } + // An empty allow_list could be considered to be a resident-key request, but // some authenticators in practice don't take it that way. Thus this code // mirrors that to better reflect reality. CTAP 2.0 leaves it as undefined
diff --git a/device/fido/virtual_ctap2_device.h b/device/fido/virtual_ctap2_device.h index 419d0a8..a8ecf93 100644 --- a/device/fido/virtual_ctap2_device.h +++ b/device/fido/virtual_ctap2_device.h
@@ -52,6 +52,10 @@ // attestedCredentialData to be included in the authenticator data of an // GetAssertion response. bool return_attested_cred_data_in_get_assertion_response = false; + // reject_large_allow_and_exclude_lists causes the authenticator to respond + // with an error if an allowList or an excludeList contains more than one + // credential ID. + bool reject_large_allow_and_exclude_lists = false; }; VirtualCtap2Device();
diff --git a/extensions/browser/disable_reason.h b/extensions/browser/disable_reason.h index ac8d4c612..53040af 100644 --- a/extensions/browser/disable_reason.h +++ b/extensions/browser/disable_reason.h
@@ -17,6 +17,9 @@ // Also carefully consider if your reason should sync to other devices, and if // so, add it to kKnownSyncableDisableReasons in // chrome/browser/extensions/extension_sync_service.cc. +// Finally, consider whether your disable reason applies to component +// extensions. Reference/update the existing list of applicable reasons in +// ExtensionsPrefs::ClearInapplicableDisableReasonsForComponentExtension. enum DisableReason { DISABLE_NONE = 0, DISABLE_USER_ACTION = 1 << 0,
diff --git a/extensions/browser/extension_prefs.cc b/extensions/browser/extension_prefs.cc index 342885b..2a02a01 100644 --- a/extensions/browser/extension_prefs.cc +++ b/extensions/browser/extension_prefs.cc
@@ -783,6 +783,22 @@ DISABLE_REASON_CLEAR); } +void ExtensionPrefs::ClearInapplicableDisableReasonsForComponentExtension( + const std::string& component_extension_id) { + static constexpr int kAllowDisableReasons = + disable_reason::DISABLE_RELOAD | + disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT | + disable_reason::DISABLE_CORRUPTED; + + // Some disable reasons incorrectly cause component extensions to never + // activate on load. See https://crbug.com/946839 for more details on why we + // do this. + ModifyDisableReasons( + component_extension_id, + kAllowDisableReasons & GetDisableReasons(component_extension_id), + DISABLE_REASON_REPLACE); +} + void ExtensionPrefs::ModifyDisableReasons(const std::string& extension_id, int reasons, DisableReasonChange change) {
diff --git a/extensions/browser/extension_prefs.h b/extensions/browser/extension_prefs.h index 20cfa62..b22bf759 100644 --- a/extensions/browser/extension_prefs.h +++ b/extensions/browser/extension_prefs.h
@@ -281,6 +281,10 @@ int disable_reasons); void ClearDisableReasons(const std::string& extension_id); + // Clears disable reasons that do not apply to component extensions. + void ClearInapplicableDisableReasonsForComponentExtension( + const std::string& component_extension_id); + // Gets the set of extensions that have been blacklisted in prefs. This will // return only the blocked extensions, not the "greylist" extensions. // TODO(oleg): Make method names consistent here, in extension service and in
diff --git a/extensions/browser/extension_registrar.cc b/extensions/browser/extension_registrar.cc index 1f7782a..ea8e8b37 100644 --- a/extensions/browser/extension_registrar.cc +++ b/extensions/browser/extension_registrar.cc
@@ -111,6 +111,7 @@ void ExtensionRegistrar::AddNewExtension( scoped_refptr<const Extension> extension) { if (extension_prefs_->IsExtensionBlacklisted(extension->id())) { + DCHECK(!Manifest::IsComponentLocation(extension->location())); // Only prefs is checked for the blacklist. We rely on callers to check the // blacklist before calling into here, e.g. CrxInstaller checks before // installation then threads through the install and pending install flow @@ -118,6 +119,7 @@ // extensions. registry_->AddBlacklisted(extension); } else if (delegate_->ShouldBlockExtension(extension.get())) { + DCHECK(!Manifest::IsComponentLocation(extension->location())); registry_->AddBlocked(extension); } else if (extension_prefs_->IsExtensionDisabled(extension->id())) { registry_->AddDisabled(extension);
diff --git a/gpu/config/gpu_crash_keys.cc b/gpu/config/gpu_crash_keys.cc index b4f99e66f..a51c27a 100644 --- a/gpu/config/gpu_crash_keys.cc +++ b/gpu/config/gpu_crash_keys.cc
@@ -24,6 +24,12 @@ "gpu-gl-context-is-virtual"); crash_reporter::CrashKeyString<20> seconds_since_last_progress_report( "seconds-since-last-progress-report"); +crash_reporter::CrashKeyString<20> seconds_since_last_suspend( + "seconds-since-last-suspend"); +crash_reporter::CrashKeyString<20> seconds_since_last_resume( + "seconds-since-last-resume"); +crash_reporter::CrashKeyString<20> seconds_since_last_logging( + "seconds-since-last-logging"); crash_reporter::CrashKeyString<20> available_physical_memory_in_mb( "available-physical-memory-in-mb");
diff --git a/gpu/config/gpu_crash_keys.h b/gpu/config/gpu_crash_keys.h index 1f1b7e7..e6bee5b 100644 --- a/gpu/config/gpu_crash_keys.h +++ b/gpu/config/gpu_crash_keys.h
@@ -29,6 +29,9 @@ extern GPU_EXPORT crash_reporter::CrashKeyString<4> gpu_gl_context_is_virtual; extern GPU_EXPORT crash_reporter::CrashKeyString<20> seconds_since_last_progress_report; +extern GPU_EXPORT crash_reporter::CrashKeyString<20> seconds_since_last_suspend; +extern GPU_EXPORT crash_reporter::CrashKeyString<20> seconds_since_last_resume; +extern GPU_EXPORT crash_reporter::CrashKeyString<20> seconds_since_last_logging; extern GPU_EXPORT crash_reporter::CrashKeyString<20> available_physical_memory_in_mb;
diff --git a/gpu/ipc/client/command_buffer_proxy_impl.cc b/gpu/ipc/client/command_buffer_proxy_impl.cc index 04af30b..a5a4c19 100644 --- a/gpu/ipc/client/command_buffer_proxy_impl.cc +++ b/gpu/ipc/client/command_buffer_proxy_impl.cc
@@ -34,6 +34,7 @@ #include "mojo/public/cpp/base/shared_memory_utils.h" #include "mojo/public/cpp/system/buffer.h" #include "mojo/public/cpp/system/platform_handle.h" +#include "ui/gfx/buffer_format_util.h" #include "ui/gfx/geometry/size.h" #include "ui/gfx/gpu_fence.h" #include "ui/gl/gl_bindings.h" @@ -435,9 +436,11 @@ image_fence_sync = GenerateFenceSyncRelease(); DCHECK(gpu::IsImageFromGpuMemoryBufferFormatSupported( - gpu_memory_buffer->GetFormat(), capabilities_)); + gpu_memory_buffer->GetFormat(), capabilities_)) + << gfx::BufferFormatToString(gpu_memory_buffer->GetFormat()); DCHECK(gpu::IsImageSizeValidForGpuMemoryBufferFormat( - gfx::Size(width, height), gpu_memory_buffer->GetFormat())); + gfx::Size(width, height), gpu_memory_buffer->GetFormat())) + << gfx::BufferFormatToString(gpu_memory_buffer->GetFormat()); GpuCommandBufferMsg_CreateImage_Params params; params.id = new_id;
diff --git a/gpu/ipc/service/gpu_watchdog_thread.cc b/gpu/ipc/service/gpu_watchdog_thread.cc index f20bda7..45288aed 100644 --- a/gpu/ipc/service/gpu_watchdog_thread.cc +++ b/gpu/ipc/service/gpu_watchdog_thread.cc
@@ -496,15 +496,12 @@ base::debug::Alias(&using_high_res_timer); #endif - base::Time current_time = base::Time::Now(); - base::TimeTicks current_timeticks = base::TimeTicks::Now(); - base::debug::Alias(¤t_time); - base::debug::Alias(¤t_timeticks); - int32_t awaiting_acknowledge = base::subtle::NoBarrier_Load(&awaiting_acknowledge_); base::debug::Alias(&awaiting_acknowledge); + base::TimeTicks before_logging_timeticks = base::TimeTicks::Now(); + // Don't log the message to stderr in release builds because the buffer // may be full. std::string message = base::StringPrintf( @@ -515,10 +512,27 @@ handler(logging::LOG_ERROR, __FILE__, __LINE__, 0, message); DLOG(ERROR) << message; + base::Time current_time = base::Time::Now(); + base::TimeTicks current_timeticks = base::TimeTicks::Now(); + base::debug::Alias(¤t_time); + base::debug::Alias(¤t_timeticks); + + int64_t since_last_logging = + (current_timeticks - before_logging_timeticks).InSeconds(); + crash_keys::seconds_since_last_logging.Set( + base::NumberToString(since_last_logging)); int64_t since_last_progress_report = (current_timeticks - last_reported_progress_timeticks_).InSeconds(); crash_keys::seconds_since_last_progress_report.Set( base::NumberToString(since_last_progress_report)); + int64_t since_last_suspend = + (current_timeticks - last_suspend_timeticks_).InSeconds(); + crash_keys::seconds_since_last_suspend.Set( + base::NumberToString(since_last_suspend)); + int64_t since_last_resume = + (current_timeticks - last_resume_timeticks_).InSeconds(); + crash_keys::seconds_since_last_resume.Set( + base::NumberToString(since_last_resume)); int64_t available_physical_memory = base::SysInfo::AmountOfAvailablePhysicalMemory() >> 20; @@ -573,10 +587,12 @@ } void GpuWatchdogThread::OnSuspend() { + last_suspend_timeticks_ = base::TimeTicks::Now(); power_suspend_ref_ = suspension_counter_.Take(); } void GpuWatchdogThread::OnResume() { + last_resume_timeticks_ = base::TimeTicks::Now(); power_suspend_ref_.reset(); }
diff --git a/gpu/ipc/service/gpu_watchdog_thread.h b/gpu/ipc/service/gpu_watchdog_thread.h index 6bb08e4..b9388fe 100644 --- a/gpu/ipc/service/gpu_watchdog_thread.h +++ b/gpu/ipc/service/gpu_watchdog_thread.h
@@ -188,6 +188,8 @@ base::TimeTicks check_timeticks_; base::TimeTicks last_reported_progress_timeticks_; + base::TimeTicks last_suspend_timeticks_; + base::TimeTicks last_resume_timeticks_; #if defined(USE_X11) XDisplay* display_;
diff --git a/ios/web/navigation/history_state_operations_inttest.mm b/ios/web/navigation/history_state_operations_inttest.mm index 3aa0f331..0acc4fc 100644 --- a/ios/web/navigation/history_state_operations_inttest.mm +++ b/ios/web/navigation/history_state_operations_inttest.mm
@@ -475,7 +475,8 @@ } // Regression test for crbug.com/788464. -TEST_P(HistoryStateOperationsTest, ReplaceStateThenReload) { +// TODO(crbug.com/950263): Investigate culprit and reenable. +TEST_P(HistoryStateOperationsTest, DISABLED_ReplaceStateThenReload) { GURL url = web::test::HttpServer::MakeUrl( "http://ios/testing/data/http_server_files/" "onload_replacestate_reload.html");
diff --git a/media/gpu/image_processor_test.cc b/media/gpu/image_processor_test.cc index 82f7b19..4349a2e 100644 --- a/media/gpu/image_processor_test.cc +++ b/media/gpu/image_processor_test.cc
@@ -30,6 +30,8 @@ FILE_PATH_LITERAL("bear_320x192.i420.yuv"); constexpr const base::FilePath::CharType* kNV12Image = FILE_PATH_LITERAL("bear_320x192.nv12.yuv"); +constexpr const base::FilePath::CharType* kRGBAImage = + FILE_PATH_LITERAL("bear_320x192.rgba"); constexpr const base::FilePath::CharType* kYV12Image = FILE_PATH_LITERAL("bear_320x192.yv12.yuv"); @@ -60,8 +62,13 @@ // TODO(crbug.com/917951): Select more appropriate number of buffers. constexpr size_t kNumBuffers = 1; LOG_ASSERT(output_image.IsMetadataLoaded()); - auto vf_validator = test::VideoFrameValidator::Create( - {output_image.Checksum()}, output_image.PixelFormat()); + // TODO(crbug.com/944823): Use VideoFrameValidator for RGB formats. + std::unique_ptr<test::VideoFrameValidator> vf_validator; + if (IsYuvPlanar(input_image.PixelFormat()) && + IsYuvPlanar(output_image.PixelFormat())) { + vf_validator = test::VideoFrameValidator::Create( + {output_image.Checksum()}, output_image.PixelFormat()); + } std::vector<std::unique_ptr<test::VideoFrameProcessor>> frame_processors; frame_processors.push_back(std::move(vf_validator)); auto ip_client = test::ImageProcessorClient::Create( @@ -89,10 +96,12 @@ // I420->NV12 // YV12->NV12 +// RGBA->NV12 INSTANTIATE_TEST_SUITE_P( ConvertToNV12, ImageProcessorSimpleParamTest, ::testing::Values(std::make_tuple(kI420Image, kNV12Image), + std::make_tuple(kRGBAImage, kNV12Image), std::make_tuple(kYV12Image, kNV12Image))); #if defined(OS_CHROMEOS)
diff --git a/media/gpu/test/image.cc b/media/gpu/test/image.cc index 6ed45d03..4f04310 100644 --- a/media/gpu/test/image.cc +++ b/media/gpu/test/image.cc
@@ -38,6 +38,8 @@ return PIXEL_FORMAT_NV12; } else if (pixel_format == "YV12") { return PIXEL_FORMAT_YV12; + } else if (pixel_format == "RGBA") { + return PIXEL_FORMAT_RGB32; } else { VLOG(2) << pixel_format << " is not supported."; return PIXEL_FORMAT_UNKNOWN;
diff --git a/net/base/network_interfaces_fuchsia.cc b/net/base/network_interfaces_fuchsia.cc index 300966e..f98a911 100644 --- a/net/base/network_interfaces_fuchsia.cc +++ b/net/base/network_interfaces_fuchsia.cc
@@ -69,10 +69,10 @@ IPAddress FuchsiaIpAddressToIPAddress(const fuchsia::net::IpAddress& addr) { if (addr.is_ipv4()) { - return IPAddress(addr.ipv4().addr.data(), addr.ipv4().addr.count()); + return IPAddress(addr.ipv4().addr.data(), addr.ipv4().addr.size()); } if (addr.is_ipv6()) { - return IPAddress(addr.ipv6().addr.data(), addr.ipv6().addr.count()); + return IPAddress(addr.ipv6().addr.data(), addr.ipv6().addr.size()); } return IPAddress(); }
diff --git a/remoting/signaling/grpc_support/grpc_async_executor.cc b/remoting/signaling/grpc_support/grpc_async_executor.cc index 03bfbf4..866d9b7 100644 --- a/remoting/signaling/grpc_support/grpc_async_executor.cc +++ b/remoting/signaling/grpc_support/grpc_async_executor.cc
@@ -4,6 +4,9 @@ #include "remoting/signaling/grpc_support/grpc_async_executor.h" +#include <algorithm> +#include <utility> + #include "base/bind.h" #include "base/callback.h" #include "base/no_destructor.h" @@ -90,15 +93,21 @@ GrpcAsyncExecutor::~GrpcAsyncExecutor() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); VLOG(0) << "# of pending RPCs at destruction: " << pending_requests_.size(); - for (auto* pending_request : pending_requests_) { - pending_request->CancelRequest(); + for (auto& pending_request : pending_requests_) { + // If the sequence itself is being destroyed, pending tasks will be dropped + // in arbitrary order without checking the weak ptr. If the dequeue task is + // destroyed earlier than the executor itself, then |pending_request| will + // already be destroyed. + if (pending_request) { + pending_request->CancelRequest(); + } } } void GrpcAsyncExecutor::ExecuteRpc(std::unique_ptr<GrpcAsyncRequest> request) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - DCHECK(pending_requests_.find(request.get()) == pending_requests_.end()); auto* unowned_request = request.get(); + DCHECK(FindRequest(unowned_request) == pending_requests_.end()); auto task = std::make_unique<DispatchTask>(); task->caller_sequence_task_runner = base::SequencedTaskRunnerHandle::Get(); task->callback = @@ -120,7 +129,12 @@ unowned_request->Start( run_task_cb, CompletionQueueDispatcher::GetInstance()->completion_queue(), task.release()); - pending_requests_.insert(unowned_request); + + // You might think that we can invert the ownership and make GrpcAsyncExecutor + // own the request instead, but this doesn't work because the gRPC completion + // queue (which runs on a different thread) expects the client context to be + // alive when you try to pop out a completed/dead event. + pending_requests_.push_back(unowned_request->GetGrpcAsyncRequestWeakPtr()); } void GrpcAsyncExecutor::OnDequeue(std::unique_ptr<GrpcAsyncRequest> request, @@ -129,12 +143,14 @@ if (!request->OnDequeue(operation_succeeded)) { VLOG(0) << "Dequeuing RPC: " << request.get(); - DCHECK(pending_requests_.find(request.get()) != pending_requests_.end()); - pending_requests_.erase(request.get()); + auto iter = FindRequest(request.get()); + DCHECK(iter != pending_requests_.end()); + pending_requests_.erase(iter); return; } VLOG(0) << "Re-enqueuing RPC: " << request.get(); + DCHECK(FindRequest(request.get()) != pending_requests_.end()); auto* unowned_request = request.get(); auto task = std::make_unique<DispatchTask>(); task->caller_sequence_task_runner = base::SequencedTaskRunnerHandle::Get(); @@ -157,4 +173,13 @@ std::move(closure).Run(); } +GrpcAsyncExecutor::PendingRequestListIter GrpcAsyncExecutor::FindRequest( + GrpcAsyncRequest* request) { + return std::find_if( + pending_requests_.begin(), pending_requests_.end(), + [request](const base::WeakPtr<GrpcAsyncRequest>& current_request) { + return current_request.get() == request; + }); +} + } // namespace remoting
diff --git a/remoting/signaling/grpc_support/grpc_async_executor.h b/remoting/signaling/grpc_support/grpc_async_executor.h index 7583a1d..444a950 100644 --- a/remoting/signaling/grpc_support/grpc_async_executor.h +++ b/remoting/signaling/grpc_support/grpc_async_executor.h
@@ -5,11 +5,10 @@ #ifndef REMOTING_SIGNALING_GRPC_SUPPORT_GRPC_ASYNC_EXECUTOR_H_ #define REMOTING_SIGNALING_GRPC_SUPPORT_GRPC_ASYNC_EXECUTOR_H_ +#include <list> #include <memory> -#include <utility> #include "base/callback_forward.h" -#include "base/containers/flat_set.h" #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/sequence_checker.h" @@ -30,6 +29,9 @@ void ExecuteRpc(std::unique_ptr<GrpcAsyncRequest> request) override; private: + using PendingRequestList = std::list<base::WeakPtr<GrpcAsyncRequest>>; + using PendingRequestListIter = PendingRequestList::iterator; + void OnDequeue(std::unique_ptr<GrpcAsyncRequest> request, bool operation_succeeded); @@ -38,11 +40,13 @@ void PostTaskToRunClosure(base::OnceClosure closure); void RunClosure(base::OnceClosure closure); + PendingRequestListIter FindRequest(GrpcAsyncRequest* request); + SEQUENCE_CHECKER(sequence_checker_); // Keep the list of pending requests so that we can cancel them at // destruction. - base::flat_set<GrpcAsyncRequest*> pending_requests_; + PendingRequestList pending_requests_; base::WeakPtrFactory<GrpcAsyncExecutor> weak_factory_; DISALLOW_COPY_AND_ASSIGN(GrpcAsyncExecutor);
diff --git a/remoting/signaling/grpc_support/grpc_async_request.cc b/remoting/signaling/grpc_support/grpc_async_request.cc index 75566bc..5b110f0 100644 --- a/remoting/signaling/grpc_support/grpc_async_request.cc +++ b/remoting/signaling/grpc_support/grpc_async_request.cc
@@ -8,8 +8,8 @@ namespace remoting { -GrpcAsyncRequest::GrpcAsyncRequest( - std::unique_ptr<grpc::ClientContext> context) { +GrpcAsyncRequest::GrpcAsyncRequest(std::unique_ptr<grpc::ClientContext> context) + : grpc_async_request_weak_factory_(this) { context_ = std::move(context); } @@ -21,4 +21,8 @@ OnRequestCanceled(); } +base::WeakPtr<GrpcAsyncRequest> GrpcAsyncRequest::GetGrpcAsyncRequestWeakPtr() { + return grpc_async_request_weak_factory_.GetWeakPtr(); +} + } // namespace remoting
diff --git a/remoting/signaling/grpc_support/grpc_async_request.h b/remoting/signaling/grpc_support/grpc_async_request.h index 83b7a50..1181ae4 100644 --- a/remoting/signaling/grpc_support/grpc_async_request.h +++ b/remoting/signaling/grpc_support/grpc_async_request.h
@@ -11,6 +11,7 @@ #include "base/callback_forward.h" #include "base/macros.h" #include "base/memory/scoped_refptr.h" +#include "base/memory/weak_ptr.h" #include "base/single_thread_task_runner.h" #include "third_party/grpc/src/include/grpcpp/support/status.h" @@ -68,6 +69,8 @@ grpc::ClientContext* context() { return context_.get(); } + base::WeakPtr<GrpcAsyncRequest> GetGrpcAsyncRequestWeakPtr(); + protected: // Called after CancelRequest() is called. virtual void OnRequestCanceled() = 0; @@ -77,6 +80,7 @@ private: std::unique_ptr<grpc::ClientContext> context_; + base::WeakPtrFactory<GrpcAsyncRequest> grpc_async_request_weak_factory_; DISALLOW_COPY_AND_ASSIGN(GrpcAsyncRequest); };
diff --git a/third_party/blink/public/BUILD.gn b/third_party/blink/public/BUILD.gn index c9b5544a..9b623ee 100644 --- a/third_party/blink/public/BUILD.gn +++ b/third_party/blink/public/BUILD.gn
@@ -395,7 +395,6 @@ "web/modules/mediastream/media_stream_video_sink.h", "web/modules/mediastream/media_stream_video_source.h", "web/modules/mediastream/media_stream_video_track.h", - "web/modules/mediastream/video_track_adapter.h", "web/modules/mediastream/video_track_adapter_settings.h", "web/modules/mediastream/web_media_stream_utils.h", "web/modules/service_worker/web_service_worker_context_client.h",
diff --git a/third_party/blink/public/common/frame/sandbox_flags.h b/third_party/blink/public/common/frame/sandbox_flags.h index 4555905..19925ce 100644 --- a/third_party/blink/public/common/frame/sandbox_flags.h +++ b/third_party/blink/public/common/frame/sandbox_flags.h
@@ -10,8 +10,7 @@ namespace blink { // See http://www.whatwg.org/specs/web-apps/current-work/#attr-iframe-sandbox -// for a list of the sandbox flags. This enum should be kept in sync with -// Source/core/frame/SandboxFlags.h, as enforced in SandboxFlags.cpp. +// for a list of the sandbox flags. enum class WebSandboxFlags : int { kNone = 0, kNavigation = 1, @@ -20,17 +19,24 @@ kForms = 1 << 3, kScripts = 1 << 4, kTopNavigation = 1 << 5, + // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=12393 kPopups = 1 << 6, kAutomaticFeatures = 1 << 7, kPointerLock = 1 << 8, kDocumentDomain = 1 << 9, + // See + // https://w3c.github.io/screen-orientation/#dfn-sandboxed-orientation-lock-browsing-context-flag. kOrientationLock = 1 << 10, kPropagatesToAuxiliaryBrowsingContexts = 1 << 11, kModals = 1 << 12, + // See + // https://w3c.github.io/presentation-api/#sandboxing-and-the-allow-presentation-keyword kPresentationController = 1 << 13, + // See https://github.com/WICG/interventions/issues/42. kTopNavigationByUserActivation = 1 << 14, + // See https://crbug.com/539938 kDownloads = 1 << 15, - kAll = -1 + kAll = -1 // Mask with all bits set to 1. }; inline constexpr WebSandboxFlags operator&(WebSandboxFlags a,
diff --git a/third_party/blink/public/mojom/payments/payment_request.mojom b/third_party/blink/public/mojom/payments/payment_request.mojom index 8f118931..034d0e2 100644 --- a/third_party/blink/public/mojom/payments/payment_request.mojom +++ b/third_party/blink/public/mojom/payments/payment_request.mojom
@@ -217,7 +217,7 @@ PaymentOptions options); // Shows the user interface with the payment details. - Show(bool is_user_gesture); + Show(bool is_user_gesture, bool wait_for_updated_details); // Updates the payment details in response to new shipping address or shipping // option.
diff --git a/third_party/blink/public/platform/web_resource_timing_info.h b/third_party/blink/public/platform/web_resource_timing_info.h index 250ae8e..02a7c0a 100644 --- a/third_party/blink/public/platform/web_resource_timing_info.h +++ b/third_party/blink/public/platform/web_resource_timing_info.h
@@ -13,9 +13,14 @@ #include "third_party/blink/public/platform/web_url_load_timing.h" #include "third_party/blink/public/platform/web_vector.h" +#if INSIDE_BLINK +#include "third_party/blink/renderer/platform/cross_thread_copier.h" // nogncheck +#endif + namespace blink { // The browser-side equivalent to this struct is content::ServerTimingInfo. +// Note: Please update operator==() whenever a new field is added. // TODO(dcheng): Migrate this struct over to Mojo so it doesn't need to be // duplicated in //content and //third_party/blink. struct WebServerTimingInfo { @@ -24,6 +29,11 @@ const WebString& description) : name(name), duration(duration), description(description) {} +#if INSIDE_BLINK + bool operator==(const WebServerTimingInfo&) const; + bool operator!=(const WebServerTimingInfo&) const; +#endif + WebString name; double duration; WebString description; @@ -33,9 +43,15 @@ // to be passed between processes. This is currently used to send timing // information about cross-process iframes for window.performance. The // browser-side equivalent to this struct is content::ResourceTimingInfo. +// Note: Please update operator==() and CrossThreadCopier whenever a new field +// is added. // TODO(dcheng): Migrate this struct over to Mojo so it doesn't need to be // duplicated in //content and //third_party/blink. struct WebResourceTimingInfo { +#if INSIDE_BLINK + PLATFORM_EXPORT bool operator==(const WebResourceTimingInfo&) const; +#endif + // The name to associate with the performance entry. For iframes, this is // typically the initial URL of the iframe resource. WebString name; @@ -76,6 +92,15 @@ WebVector<WebServerTimingInfo> server_timing; }; +#if INSIDE_BLINK +template <> +struct CrossThreadCopier<WebResourceTimingInfo> { + STATIC_ONLY(CrossThreadCopier); + typedef WebResourceTimingInfo Type; + PLATFORM_EXPORT static Type Copy(const WebResourceTimingInfo&); +}; +#endif + } // namespace blink #endif
diff --git a/third_party/blink/public/platform/web_url_load_timing.h b/third_party/blink/public/platform/web_url_load_timing.h index 6aca8fa..a5ab4972 100644 --- a/third_party/blink/public/platform/web_url_load_timing.h +++ b/third_party/blink/public/platform/web_url_load_timing.h
@@ -37,6 +37,7 @@ #if INSIDE_BLINK #include "base/memory/scoped_refptr.h" +#include "third_party/blink/renderer/platform/cross_thread_copier.h" // nogncheck #endif namespace blink { @@ -119,12 +120,23 @@ BLINK_PLATFORM_EXPORT WebURLLoadTiming& operator=( scoped_refptr<ResourceLoadTiming>); BLINK_PLATFORM_EXPORT operator scoped_refptr<ResourceLoadTiming>() const; + BLINK_PLATFORM_EXPORT WebURLLoadTiming DeepCopy() const; + BLINK_PLATFORM_EXPORT bool operator==(const WebURLLoadTiming&) const; #endif private: WebPrivatePtr<ResourceLoadTiming> private_; }; +#if INSIDE_BLINK +template <> +struct CrossThreadCopier<WebURLLoadTiming> { + STATIC_ONLY(CrossThreadCopier); + typedef WebURLLoadTiming Type; + PLATFORM_EXPORT static Type Copy(const WebURLLoadTiming&); +}; +#endif + } // namespace blink #endif
diff --git a/third_party/blink/public/web/web_navigation_params.h b/third_party/blink/public/web/web_navigation_params.h index 265633c..d83236c 100644 --- a/third_party/blink/public/web/web_navigation_params.h +++ b/third_party/blink/public/web/web_navigation_params.h
@@ -79,8 +79,8 @@ // Whether the navigation is a result of client redirect. bool is_client_redirect = false; - // Whether the navigation initiator frame has the |kSandboxDownloads| bit set - // in its sandbox flags set. + // Whether the navigation initiator frame has the + // |WebSandboxFlags::kDownloads| bit set in its sandbox flags set. bool initiator_frame_has_download_sandbox_flag = false; // Whether the navigation initiator frame is an ad frame.
diff --git a/third_party/blink/renderer/core/clipboard/data_object_item.h b/third_party/blink/renderer/core/clipboard/data_object_item.h index 5b051db..e75fe30 100644 --- a/third_party/blink/renderer/core/clipboard/data_object_item.h +++ b/third_party/blink/renderer/core/clipboard/data_object_item.h
@@ -64,8 +64,10 @@ static DataObjectItem* CreateFromClipboard(const String& type, uint64_t sequence_number); - DataObjectItem(ItemKind, const String& type); - DataObjectItem(ItemKind, const String& type, uint64_t sequence_number); + explicit DataObjectItem(ItemKind, const String& type); + explicit DataObjectItem(ItemKind, + const String& type, + uint64_t sequence_number); ItemKind Kind() const { return kind_; } String GetType() const { return type_; }
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer.h b/third_party/blink/renderer/core/clipboard/data_transfer.h index 6cfbb54b..f1e4461 100644 --- a/third_party/blink/renderer/core/clipboard/data_transfer.h +++ b/third_party/blink/renderer/core/clipboard/data_transfer.h
@@ -72,7 +72,9 @@ DataTransferAccessPolicy, DataObject*); - DataTransfer(DataTransferType, DataTransferAccessPolicy, DataObject*); + explicit DataTransfer(DataTransferType, + DataTransferAccessPolicy, + DataObject*); ~DataTransfer() override; bool IsForCopyAndPaste() const { return transfer_type_ == kCopyAndPaste; }
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer_item.h b/third_party/blink/renderer/core/clipboard/data_transfer_item.h index 62255e4..c930a457 100644 --- a/third_party/blink/renderer/core/clipboard/data_transfer_item.h +++ b/third_party/blink/renderer/core/clipboard/data_transfer_item.h
@@ -50,7 +50,7 @@ DEFINE_WRAPPERTYPEINFO(); public: - DataTransferItem(DataTransfer*, DataObjectItem*); + explicit DataTransferItem(DataTransfer*, DataObjectItem*); String kind() const; String type() const;
diff --git a/third_party/blink/renderer/core/clipboard/data_transfer_item_list.h b/third_party/blink/renderer/core/clipboard/data_transfer_item_list.h index 1d6b18b..0c0df5f 100644 --- a/third_party/blink/renderer/core/clipboard/data_transfer_item_list.h +++ b/third_party/blink/renderer/core/clipboard/data_transfer_item_list.h
@@ -49,7 +49,7 @@ DEFINE_WRAPPERTYPEINFO(); public: - DataTransferItemList(DataTransfer*, DataObject*); + explicit DataTransferItemList(DataTransfer*, DataObject*); uint32_t length() const; DataTransferItem* item(uint32_t index);
diff --git a/third_party/blink/renderer/core/dom/document.cc b/third_party/blink/renderer/core/dom/document.cc index 52412cef..b561dfd 100644 --- a/third_party/blink/renderer/core/dom/document.cc +++ b/third_party/blink/renderer/core/dom/document.cc
@@ -4177,7 +4177,7 @@ } if (http_refresh_type == kHttpRefreshFromMetaTag && - IsSandboxed(kSandboxAutomaticFeatures)) { + IsSandboxed(WebSandboxFlags::kAutomaticFeatures)) { String message = "Refused to execute the redirect specified via '<meta " "http-equiv='refresh' content='...'>'. The document is sandboxed, and " @@ -5228,7 +5228,7 @@ // browsing context. if (!GetSecurityOrigin()->CanAccessCookies()) { - if (IsSandboxed(kSandboxOrigin)) + if (IsSandboxed(WebSandboxFlags::kOrigin)) exception_state.ThrowSecurityError( "The document is sandboxed and lacks the 'allow-same-origin' flag."); else if (Url().ProtocolIs("data")) @@ -5259,7 +5259,7 @@ // browsing context. if (!GetSecurityOrigin()->CanAccessCookies()) { - if (IsSandboxed(kSandboxOrigin)) + if (IsSandboxed(WebSandboxFlags::kOrigin)) exception_state.ThrowSecurityError( "The document is sandboxed and lacks the 'allow-same-origin' flag."); else if (Url().ProtocolIs("data")) @@ -5308,7 +5308,7 @@ return; } - if (IsSandboxed(kSandboxDocumentDomain)) { + if (IsSandboxed(WebSandboxFlags::kDocumentDomain)) { exception_state.ThrowSecurityError( "Assignment is forbidden for sandboxed iframes."); return; @@ -6197,7 +6197,7 @@ mojom::ConsoleMessageLevel::kError, "Error with Feature-Policy header: " + message)); } - if (GetSandboxFlags() != kSandboxNone && + if (GetSandboxFlags() != WebSandboxFlags::kNone && RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) { // The sandbox flags might have come from CSP header or the browser; in such // cases the sandbox is not part of the container policy. They are added @@ -6347,8 +6347,9 @@ // Instead, force a Document loaded from a MHTML archive to be sandboxed, // providing exceptions only for creating new windows. sandbox_flags |= - kSandboxAll & - ~(kSandboxPopups | kSandboxPropagatesToAuxiliaryBrowsingContexts); + (WebSandboxFlags::kAll & + ~(WebSandboxFlags::kPopups | + WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts)); } // In the common case, create the security context from the currently // loading URL with a fresh content security policy. @@ -6392,7 +6393,7 @@ } } - if (IsSandboxed(kSandboxOrigin)) { + if (IsSandboxed(WebSandboxFlags::kOrigin)) { DCHECK(!initializer.ContextDocument()); scoped_refptr<SecurityOrigin> sandboxed_origin = initializer.OriginToCommit() ? initializer.OriginToCommit() @@ -6473,7 +6474,7 @@ GetMutableSecurityOrigin()->SetOpaqueOriginIsPotentiallyTrustworthy(true); ParsedFeaturePolicy declared_policy = {}; - if (GetSandboxFlags() != kSandboxNone && + if (GetSandboxFlags() != WebSandboxFlags::kNone && RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) { // If any sandbox flags are enforced above they should also be added as // part of a declared policy to properly initialize the sandbox feature @@ -6560,7 +6561,7 @@ // However, there is an exception for cases when the script should bypass the // main world's CSP (such as for privileged isolated worlds). See // https://crbug.com/811528. - if (IsSandboxed(kSandboxScripts) && + if (IsSandboxed(WebSandboxFlags::kScripts) && !ContentSecurityPolicy::ShouldBypassMainWorld(this)) { // FIXME: This message should be moved off the console once a solution to // https://bugs.webkit.org/show_bug.cgi?id=103274 exists. @@ -7378,7 +7379,7 @@ bool Document::IsSecureContext() const { bool is_secure = secure_context_state_ == SecureContextState::kSecure; - if (GetSandboxFlags() != kSandboxNone) { + if (GetSandboxFlags() != WebSandboxFlags::kNone) { UseCounter::Count( *this, is_secure ? WebFeature::kSecureContextCheckForSandboxedOriginPassed
diff --git a/third_party/blink/renderer/core/dom/document_init.cc b/third_party/blink/renderer/core/dom/document_init.cc index d8c9e39..6e81911 100644 --- a/third_party/blink/renderer/core/dom/document_init.cc +++ b/third_party/blink/renderer/core/dom/document_init.cc
@@ -102,7 +102,7 @@ // so that the blocked document appears to be a normal cross-origin document's // load per CSP spec: https://www.w3.org/TR/CSP3/#directive-frame-ancestors. if (loader->WasBlockedAfterCSP()) { - flags |= kSandboxOrigin; + flags |= WebSandboxFlags::kOrigin; } return flags;
diff --git a/third_party/blink/renderer/core/dom/document_test.cc b/third_party/blink/renderer/core/dom/document_test.cc index 415d791..7aa7675d 100644 --- a/third_party/blink/renderer/core/dom/document_test.cc +++ b/third_party/blink/renderer/core/dom/document_test.cc
@@ -596,12 +596,12 @@ scoped_refptr<SecurityOrigin> origin = SecurityOrigin::CreateFromString("http://example.test"); GetDocument().SetSecurityOrigin(origin); - SandboxFlags mask = kSandboxNavigation; + SandboxFlags mask = WebSandboxFlags::kNavigation; GetDocument().EnforceSandboxFlags(mask); EXPECT_EQ(origin, GetDocument().GetSecurityOrigin()); EXPECT_FALSE(GetDocument().GetSecurityOrigin()->IsPotentiallyTrustworthy()); - mask |= kSandboxOrigin; + mask |= WebSandboxFlags::kOrigin; GetDocument().EnforceSandboxFlags(mask); EXPECT_TRUE(GetDocument().GetSecurityOrigin()->IsOpaque()); EXPECT_FALSE(GetDocument().GetSecurityOrigin()->IsPotentiallyTrustworthy()); @@ -879,7 +879,7 @@ scoped_refptr<SecurityOrigin> origin = SecurityOrigin::CreateFromString("https://test.com"); GetDocument().SetSecurityOrigin(origin); - SandboxFlags mask = kSandboxOrigin; + SandboxFlags mask = WebSandboxFlags::kOrigin; GetDocument().EnforceSandboxFlags(mask); GetDocument().SetURL(KURL("https://test.com/foobar/document")); @@ -1077,7 +1077,7 @@ INSTANTIATE_TEST_SUITE_P(, IsolatedWorldCSPTest, testing::Values(true, false)); TEST_F(DocumentTest, CanExecuteScriptsWithSandboxAndIsolatedWorld) { - constexpr SandboxFlags kSandboxMask = kSandboxScripts; + constexpr SandboxFlags kSandboxMask = WebSandboxFlags::kScripts; GetDocument().EnforceSandboxFlags(kSandboxMask); // With FeaturePolicyForSandbox, all the sandbox flags must be explicitly // converted to equivalent feature policies. Since sandbox is enforced above,
diff --git a/third_party/blink/renderer/core/editing/caret_display_item_client.cc b/third_party/blink/renderer/core/editing/caret_display_item_client.cc index eb0d5c20..30253cf 100644 --- a/third_party/blink/renderer/core/editing/caret_display_item_client.cc +++ b/third_party/blink/renderer/core/editing/caret_display_item_client.cc
@@ -58,17 +58,17 @@ if (!layout_object) return nullptr; + auto* caret_layout_object = DynamicTo<LayoutBlock>(layout_object); // if caretNode is a block and caret is inside it then caret should be painted // by that block - bool painted_by_block = - layout_object->IsLayoutBlock() && CaretRendersInsideNode(node); + bool painted_by_block = caret_layout_object && CaretRendersInsideNode(node); // TODO(yoichio): This function is called at least // DocumentLifeCycle::LayoutClean but caretRendersInsideNode above can // layout. Thus |node->layoutObject()| can be changed then this is bad // design. We should make caret painting algorithm clean. CHECK_EQ(layout_object, node->GetLayoutObject()) << "Layout tree should not changed"; - return painted_by_block ? ToLayoutBlock(layout_object) + return painted_by_block ? caret_layout_object : layout_object->ContainingBlock(); }
diff --git a/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc b/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc index 6d4de7a..97832e6 100644 --- a/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc +++ b/third_party/blink/renderer/core/editing/caret_display_item_client_test.cc
@@ -81,7 +81,7 @@ Text* text = AppendTextNode("Hello, World!"); UpdateAllLifecyclePhasesForCaretTest(); - const auto* block = ToLayoutBlock(GetDocument().body()->GetLayoutObject()); + const auto* block = To<LayoutBlock>(GetDocument().body()->GetLayoutObject()); // Focus the body. Should invalidate the new caret. GetDocument().View()->SetTracksPaintInvalidations(true); @@ -232,8 +232,8 @@ auto* block_element1 = AppendBlock("Block1"); auto* block_element2 = AppendBlock("Block2"); UpdateAllLifecyclePhasesForCaretTest(); - auto* block1 = ToLayoutBlock(block_element1->GetLayoutObject()); - auto* block2 = ToLayoutBlock(block_element2->GetLayoutObject()); + auto* block1 = To<LayoutBlock>(block_element1->GetLayoutObject()); + auto* block2 = To<LayoutBlock>(block_element2->GetLayoutObject()); // Set caret into block2. GetDocument().body()->focus(); @@ -295,7 +295,7 @@ Text* text = AppendTextNode("Hello, World!"); GetDocument().body()->focus(); UpdateAllLifecyclePhasesForCaretTest(); - const auto* block = ToLayoutBlock(GetDocument().body()->GetLayoutObject()); + const auto* block = To<LayoutBlock>(GetDocument().body()->GetLayoutObject()); LayoutRect caret_visual_rect = GetCaretDisplayItemClient().VisualRect(); EXPECT_EQ(1, caret_visual_rect.Width()); @@ -345,7 +345,7 @@ GetDocument().GetPage()->GetFocusController().SetFocused(true); auto* container = GetDocument().getElementById("container"); auto* editor = GetDocument().getElementById("editor"); - auto* editor_block = ToLayoutBlock(editor->GetLayoutObject()); + auto* editor_block = To<LayoutBlock>(editor->GetLayoutObject()); Selection().SetSelectionAndEndTyping( SelectionInDOMTree::Builder().Collapse(Position(editor, 0)).Build()); UpdateAllLifecyclePhasesForCaretTest();
diff --git a/third_party/blink/renderer/core/editing/frame_selection_test.cc b/third_party/blink/renderer/core/editing/frame_selection_test.cc index cd580127..24cf1038 100644 --- a/third_party/blink/renderer/core/editing/frame_selection_test.cc +++ b/third_party/blink/renderer/core/editing/frame_selection_test.cc
@@ -130,7 +130,7 @@ SelectionInDOMTree::Builder().Collapse(Position(text, 0)).Build()); UpdateAllLifecyclePhasesForTest(); EXPECT_TRUE(Selection().ComputeVisibleSelectionInDOMTree().IsCaret()); - EXPECT_TRUE(ToLayoutBlock(GetDocument().body()->GetLayoutObject()) + EXPECT_TRUE(To<LayoutBlock>(GetDocument().body()->GetLayoutObject()) ->ShouldPaintCursorCaret()); unsigned start_count = LayoutCount();
diff --git a/third_party/blink/renderer/core/editing/iterators/text_iterator.cc b/third_party/blink/renderer/core/editing/iterators/text_iterator.cc index 447d7c83..e04a90b 100644 --- a/third_party/blink/renderer/core/editing/iterators/text_iterator.cc +++ b/third_party/blink/renderer/core/editing/iterators/text_iterator.cc
@@ -716,7 +716,7 @@ node_->GetLayoutObject()->Style()->Visibility() != EVisibility::kVisible || (node_->GetLayoutObject()->IsLayoutBlockFlow() && - !ToLayoutBlock(node_->GetLayoutObject())->Size().Height() && + !To<LayoutBlock>(node_->GetLayoutObject())->Size().Height() && !IsHTMLBodyElement(*node_))) return false;
diff --git a/third_party/blink/renderer/core/editing/text_offset_mapping.cc b/third_party/blink/renderer/core/editing/text_offset_mapping.cc index 3e9cdcbe..8143a8e2 100644 --- a/third_party/blink/renderer/core/editing/text_offset_mapping.cc +++ b/third_party/blink/renderer/core/editing/text_offset_mapping.cc
@@ -91,9 +91,10 @@ // |LayoutBlockFlow|. const LayoutBlockFlow* ComputeInlineContentsAsBlockFlow( const LayoutObject& layout_object) { - const LayoutBlock* const block = layout_object.IsLayoutBlock() - ? &ToLayoutBlock(layout_object) - : layout_object.ContainingBlock(); + const LayoutBlock* block = DynamicTo<LayoutBlock>(layout_object); + if (!block) + block = layout_object.ContainingBlock(); + DCHECK(block) << layout_object; if (!block->IsLayoutBlockFlow()) return nullptr;
diff --git a/third_party/blink/renderer/core/editing/visible_units.cc b/third_party/blink/renderer/core/editing/visible_units.cc index 2efc1db..84e6a01 100644 --- a/third_party/blink/renderer/core/editing/visible_units.cc +++ b/third_party/blink/renderer/core/editing/visible_units.cc
@@ -934,7 +934,7 @@ if (layout_object->IsLayoutBlockFlow() || layout_object->IsFlexibleBoxIncludingNG() || layout_object->IsLayoutGrid()) { - if (ToLayoutBlock(layout_object)->LogicalHeight() || + if (To<LayoutBlock>(layout_object)->LogicalHeight() || anchor_node->GetDocument().body() == anchor_node) { if (!HasRenderedNonAnonymousDescendantsWithHeight(layout_object)) return position.AtFirstEditingPositionForNode();
diff --git a/third_party/blink/renderer/core/execution_context/remote_security_context.cc b/third_party/blink/renderer/core/execution_context/remote_security_context.cc index 6f210cbf..d8138e2 100644 --- a/third_party/blink/renderer/core/execution_context/remote_security_context.cc +++ b/third_party/blink/renderer/core/execution_context/remote_security_context.cc
@@ -41,7 +41,7 @@ } void RemoteSecurityContext::ResetSandboxFlags() { - sandbox_flags_ = kSandboxNone; + sandbox_flags_ = WebSandboxFlags::kNone; } } // namespace blink
diff --git a/third_party/blink/renderer/core/execution_context/security_context.cc b/third_party/blink/renderer/core/execution_context/security_context.cc index bd632ed..1ee2e2b 100644 --- a/third_party/blink/renderer/core/execution_context/security_context.cc +++ b/third_party/blink/renderer/core/execution_context/security_context.cc
@@ -49,7 +49,7 @@ } SecurityContext::SecurityContext() - : sandbox_flags_(kSandboxNone), + : sandbox_flags_(WebSandboxFlags::kNone), address_space_(mojom::IPAddressSpace::kPublic), insecure_request_policy_(kLeaveInsecureRequestsAlone), require_safe_types_(false) {} @@ -70,34 +70,34 @@ content_security_policy_ = content_security_policy; } -bool SecurityContext::IsSandboxed(SandboxFlag mask) const { +bool SecurityContext::IsSandboxed(WebSandboxFlags mask) const { if (RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled()) { switch (mask) { - case kSandboxAll: + case WebSandboxFlags::kAll: NOTREACHED(); break; - case kSandboxTopNavigation: + case WebSandboxFlags::kTopNavigation: return !feature_policy_->IsFeatureEnabled( mojom::FeaturePolicyFeature::kTopNavigation); - case kSandboxForms: + case WebSandboxFlags::kForms: return !feature_policy_->IsFeatureEnabled( mojom::FeaturePolicyFeature::kFormSubmission); - case kSandboxScripts: + case WebSandboxFlags::kScripts: return !feature_policy_->IsFeatureEnabled( mojom::FeaturePolicyFeature::kScript); - case kSandboxPopups: + case WebSandboxFlags::kPopups: return !feature_policy_->IsFeatureEnabled( mojom::FeaturePolicyFeature::kPopups); - case kSandboxPointerLock: + case WebSandboxFlags::kPointerLock: return !feature_policy_->IsFeatureEnabled( mojom::FeaturePolicyFeature::kPointerLock); - case kSandboxOrientationLock: + case WebSandboxFlags::kOrientationLock: return !feature_policy_->IsFeatureEnabled( mojom::FeaturePolicyFeature::kOrientationLock); - case kSandboxModals: + case WebSandboxFlags::kModals: return !feature_policy_->IsFeatureEnabled( mojom::FeaturePolicyFeature::kModals); - case kSandboxPresentationController: + case WebSandboxFlags::kPresentationController: return !feature_policy_->IsFeatureEnabled( mojom::FeaturePolicyFeature::kPresentation); default: @@ -105,18 +105,18 @@ break; } } - return sandbox_flags_ & mask; + return (sandbox_flags_ & mask) != WebSandboxFlags::kNone; } -void SecurityContext::EnforceSandboxFlags(SandboxFlags mask) { +void SecurityContext::EnforceSandboxFlags(WebSandboxFlags mask) { ApplySandboxFlags(mask); } -void SecurityContext::ApplySandboxFlags(SandboxFlags mask, +void SecurityContext::ApplySandboxFlags(WebSandboxFlags mask, bool is_potentially_trustworthy) { sandbox_flags_ |= mask; - if (IsSandboxed(kSandboxOrigin) && GetSecurityOrigin() && + if (IsSandboxed(WebSandboxFlags::kOrigin) && GetSecurityOrigin() && !GetSecurityOrigin()->IsOpaque()) { scoped_refptr<SecurityOrigin> security_origin = GetSecurityOrigin()->DeriveNewOpaqueOrigin();
diff --git a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc index fdc1982..3493baa 100644 --- a/third_party/blink/renderer/core/exported/local_frame_client_impl.cc +++ b/third_party/blink/renderer/core/exported/local_frame_client_impl.cc
@@ -564,7 +564,7 @@ frame->Client()->Opener() == ToCoreFrame(web_frame_); navigation_info->initiator_frame_has_download_sandbox_flag = frame->GetSecurityContext() && - frame->GetSecurityContext()->IsSandboxed(kSandboxDownloads); + frame->GetSecurityContext()->IsSandboxed(WebSandboxFlags::kDownloads); navigation_info->initiator_frame_is_ad = frame->IsAdSubframe(); }
diff --git a/third_party/blink/renderer/core/exported/web_frame_test.cc b/third_party/blink/renderer/core/exported/web_frame_test.cc index ca2ee4f..6bc5842 100644 --- a/third_party/blink/renderer/core/exported/web_frame_test.cc +++ b/third_party/blink/renderer/core/exported/web_frame_test.cc
@@ -8670,7 +8670,7 @@ Document* document = web_view->MainFrameImpl()->GetFrame()->GetDocument(); LayoutBlock* container = - ToLayoutBlock(document->getElementById("container")->GetLayoutObject()); + To<LayoutBlock>(document->getElementById("container")->GetLayoutObject()); LayoutBox* percent_height_in_anonymous = ToLayoutBox(document->getElementById("percent-height-in-anonymous") ->GetLayoutObject());
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc index 27ec352c..50a865f 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy.cc +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.cc
@@ -152,7 +152,7 @@ override_inline_style_allowed_(false), script_hash_algorithms_used_(kContentSecurityPolicyHashAlgorithmNone), style_hash_algorithms_used_(kContentSecurityPolicyHashAlgorithmNone), - sandbox_mask_(0), + sandbox_mask_(WebSandboxFlags::kNone), treat_as_public_address_(false), require_trusted_types_(false), insecure_request_policy_(kLeaveInsecureRequestsAlone) {} @@ -191,7 +191,7 @@ // Set mixed content checking and sandbox flags, then dump all the parsing // error messages, then poke at histograms. - if (sandbox_mask_ != kSandboxNone) { + if (sandbox_mask_ != WebSandboxFlags::kNone) { Count(WebFeature::kSandboxViaCSP); delegate_->SetSandboxFlags(sandbox_mask_); }
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy.h b/third_party/blink/renderer/core/frame/csp/content_security_policy.h index fd052b2..7a2d6bd 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy.h +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy.h
@@ -73,7 +73,7 @@ class SourceLocation; enum class ResourceType : uint8_t; -typedef int SandboxFlags; +using SandboxFlags = WebSandboxFlags; typedef HeapVector<Member<CSPDirectiveList>> CSPDirectiveListVector; typedef HeapVector<Member<ConsoleMessage>> ConsoleMessageVector; typedef std::pair<String, ContentSecurityPolicyHeaderType> CSPHeaderAndType;
diff --git a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc index 3ec5854..339210c 100644 --- a/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc +++ b/third_party/blink/renderer/core/frame/csp/content_security_policy_test.cc
@@ -1593,7 +1593,7 @@ EXPECT_EQ(kLeaveInsecureRequestsAlone, csp->GetInsecureRequestPolicy()); EXPECT_FALSE(csp->HasHeaderDeliveredPolicy()); EXPECT_FALSE(csp->SupportsWasmEval()); - EXPECT_EQ(kSandboxNone, csp->GetSandboxMask()); + EXPECT_EQ(WebSandboxFlags::kNone, csp->GetSandboxMask()); EXPECT_FALSE( csp->HasPolicyFromSource(kContentSecurityPolicyHeaderSourceHTTP)); }
diff --git a/third_party/blink/renderer/core/frame/dom_window.cc b/third_party/blink/renderer/core/frame/dom_window.cc index 791af2f..8b4e29f 100644 --- a/third_party/blink/renderer/core/frame/dom_window.cc +++ b/third_party/blink/renderer/core/frame/dom_window.cc
@@ -251,18 +251,19 @@ KURL target_url = local_dom_window ? local_dom_window->document()->Url() : KURL(NullURL(), target_origin->ToString()); - if (GetFrame()->GetSecurityContext()->IsSandboxed(kSandboxOrigin) || - accessing_window->document()->IsSandboxed(kSandboxOrigin)) { + if (GetFrame()->GetSecurityContext()->IsSandboxed(WebSandboxFlags::kOrigin) || + accessing_window->document()->IsSandboxed(WebSandboxFlags::kOrigin)) { message = "Blocked a frame at \"" + SecurityOrigin::Create(active_url)->ToString() + "\" from accessing a frame at \"" + SecurityOrigin::Create(target_url)->ToString() + "\". "; - if (GetFrame()->GetSecurityContext()->IsSandboxed(kSandboxOrigin) && - accessing_window->document()->IsSandboxed(kSandboxOrigin)) + if (GetFrame()->GetSecurityContext()->IsSandboxed( + WebSandboxFlags::kOrigin) && + accessing_window->document()->IsSandboxed(WebSandboxFlags::kOrigin)) return "Sandbox access violation: " + message + " Both frames are sandboxed and lack the \"allow-same-origin\" " "flag."; - if (GetFrame()->GetSecurityContext()->IsSandboxed(kSandboxOrigin)) + if (GetFrame()->GetSecurityContext()->IsSandboxed(WebSandboxFlags::kOrigin)) return "Sandbox access violation: " + message + " The frame being accessed is sandboxed and lacks the " "\"allow-same-origin\" flag.";
diff --git a/third_party/blink/renderer/core/frame/frame_owner.h b/third_party/blink/renderer/core/frame/frame_owner.h index 810b82e..c31b88e 100644 --- a/third_party/blink/renderer/core/frame/frame_owner.h +++ b/third_party/blink/renderer/core/frame/frame_owner.h
@@ -92,7 +92,9 @@ Frame* ContentFrame() const override { return nullptr; } void SetContentFrame(Frame&) override {} void ClearContentFrame() override {} - SandboxFlags GetSandboxFlags() const override { return kSandboxNone; } + SandboxFlags GetSandboxFlags() const override { + return WebSandboxFlags::kNone; + } void AddResourceTiming(const ResourceTimingInfo&) override {} void DispatchLoad() override {} bool CanRenderFallbackContent() const override { return false; }
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 46315a0..5fc087b 100644 --- a/third_party/blink/renderer/core/frame/local_dom_window.cc +++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
@@ -245,7 +245,8 @@ document = DOMImplementation::createDocument( mime_type, init, init.GetFrame() ? init.GetFrame()->InViewSourceMode() : false); - if (document->IsPluginDocument() && document->IsSandboxed(kSandboxPlugins)) + if (document->IsPluginDocument() && + document->IsSandboxed(WebSandboxFlags::kPlugins)) document = MakeGarbageCollected<SinkDocument>(init); } @@ -667,7 +668,7 @@ if (!GetFrame()) return; - if (document()->IsSandboxed(kSandboxModals)) { + if (document()->IsSandboxed(WebSandboxFlags::kModals)) { UseCounter::Count(document(), WebFeature::kDialogInSandboxedContext); GetFrameConsole()->AddMessage(ConsoleMessage::Create( mojom::ConsoleMessageSource::kSecurity, @@ -697,7 +698,7 @@ if (!GetFrame()) return false; - if (document()->IsSandboxed(kSandboxModals)) { + if (document()->IsSandboxed(WebSandboxFlags::kModals)) { UseCounter::Count(document(), WebFeature::kDialogInSandboxedContext); GetFrameConsole()->AddMessage(ConsoleMessage::Create( mojom::ConsoleMessageSource::kSecurity, @@ -729,7 +730,7 @@ if (!GetFrame()) return String(); - if (document()->IsSandboxed(kSandboxModals)) { + if (document()->IsSandboxed(WebSandboxFlags::kModals)) { UseCounter::Count(document(), WebFeature::kDialogInSandboxedContext); GetFrameConsole()->AddMessage(ConsoleMessage::Create( mojom::ConsoleMessageSource::kSecurity,
diff --git a/third_party/blink/renderer/core/frame/local_frame.cc b/third_party/blink/renderer/core/frame/local_frame.cc index cf4c2653..4e3a44a 100644 --- a/third_party/blink/renderer/core/frame/local_frame.cc +++ b/third_party/blink/renderer/core/frame/local_frame.cc
@@ -1073,7 +1073,7 @@ WebFeature::kOpenerNavigationWithoutGesture); } - if (GetSecurityContext()->IsSandboxed(kSandboxNavigation)) { + if (GetSecurityContext()->IsSandboxed(WebSandboxFlags::kNavigation)) { if (!target_frame.Tree().IsDescendantOf(this) && !target_frame.IsMainFrame()) { PrintNavigationErrorMessage( @@ -1088,8 +1088,8 @@ // 'allow-popups' flag is specified, or if the if (target_frame.IsMainFrame() && target_frame != Tree().Top() && GetSecurityContext()->IsSandboxed( - kSandboxPropagatesToAuxiliaryBrowsingContexts) && - (GetSecurityContext()->IsSandboxed(kSandboxPopups) || + WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts) && + (GetSecurityContext()->IsSandboxed(WebSandboxFlags::kPopups) || target_frame.Client()->Opener() != this)) { PrintNavigationErrorMessage( target_frame, @@ -1102,9 +1102,9 @@ // Top navigation is forbidden unless opted-in. allow-top-navigation or // allow-top-navigation-by-user-activation will also skips origin checks. if (target_frame == Tree().Top()) { - if (GetSecurityContext()->IsSandboxed(kSandboxTopNavigation) && + if (GetSecurityContext()->IsSandboxed(WebSandboxFlags::kTopNavigation) && GetSecurityContext()->IsSandboxed( - kSandboxTopNavigationByUserActivation)) { + WebSandboxFlags::kTopNavigationByUserActivation)) { PrintNavigationErrorMessage( target_frame, "The frame attempting navigation of the top-level window is " @@ -1113,9 +1113,9 @@ return false; } - if (GetSecurityContext()->IsSandboxed(kSandboxTopNavigation) && + if (GetSecurityContext()->IsSandboxed(WebSandboxFlags::kTopNavigation) && !GetSecurityContext()->IsSandboxed( - kSandboxTopNavigationByUserActivation) && + WebSandboxFlags::kTopNavigationByUserActivation) && !LocalFrame::HasTransientUserActivation(this)) { // With only 'allow-top-navigation-by-user-activation' (but not // 'allow-top-navigation'), top navigation requires a user gesture.
diff --git a/third_party/blink/renderer/core/frame/mhtml_loading_test.cc b/third_party/blink/renderer/core/frame/mhtml_loading_test.cc index da856d3..bfa6c37 100644 --- a/third_party/blink/renderer/core/frame/mhtml_loading_test.cc +++ b/third_party/blink/renderer/core/frame/mhtml_loading_test.cc
@@ -119,8 +119,9 @@ // Full sandboxing with the exception to new top-level windows should be // turned on. - EXPECT_EQ(kSandboxAll & ~(kSandboxPopups | - kSandboxPropagatesToAuxiliaryBrowsingContexts), + EXPECT_EQ(WebSandboxFlags::kAll & + ~(WebSandboxFlags::kPopups | + WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts), document->GetSandboxFlags()); // MHTML document should be loaded into unique origin. @@ -138,8 +139,9 @@ Document* child_document = child_frame->GetDocument(); ASSERT_TRUE(child_document); - EXPECT_EQ(kSandboxAll & ~(kSandboxPopups | - kSandboxPropagatesToAuxiliaryBrowsingContexts), + EXPECT_EQ(WebSandboxFlags::kAll & + ~(WebSandboxFlags::kPopups | + WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts), child_document->GetSandboxFlags()); // MHTML document should be loaded into unique origin. @@ -163,8 +165,9 @@ // Full sandboxing with the exception to new top-level windows should be // turned on. - EXPECT_EQ(kSandboxAll & ~(kSandboxPopups | - kSandboxPropagatesToAuxiliaryBrowsingContexts), + EXPECT_EQ(WebSandboxFlags::kAll & + ~(WebSandboxFlags::kPopups | + WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts), document->GetSandboxFlags()); // MHTML document should be loaded into unique origin.
diff --git a/third_party/blink/renderer/core/frame/remote_frame.cc b/third_party/blink/renderer/core/frame/remote_frame.cc index 116006c..b28e5292 100644 --- a/third_party/blink/renderer/core/frame/remote_frame.cc +++ b/third_party/blink/renderer/core/frame/remote_frame.cc
@@ -108,13 +108,13 @@ is_opener_navigation = frame->Client()->Opener() == this; initiator_frame_has_download_sandbox_flag = frame->GetSecurityContext() && - frame->GetSecurityContext()->IsSandboxed(kSandboxDownloads); + frame->GetSecurityContext()->IsSandboxed(WebSandboxFlags::kDownloads); initiator_frame_is_ad = frame->IsAdSubframe(); } bool current_frame_has_download_sandbox_flag = GetSecurityContext() && - GetSecurityContext()->IsSandboxed(kSandboxDownloads); + GetSecurityContext()->IsSandboxed(WebSandboxFlags::kDownloads); bool has_download_sandbox_flag = initiator_frame_has_download_sandbox_flag || current_frame_has_download_sandbox_flag;
diff --git a/third_party/blink/renderer/core/frame/sandbox_flags.cc b/third_party/blink/renderer/core/frame/sandbox_flags.cc index 12a9250..05de213 100644 --- a/third_party/blink/renderer/core/frame/sandbox_flags.cc +++ b/third_party/blink/renderer/core/frame/sandbox_flags.cc
@@ -45,15 +45,17 @@ const SandboxFlagFeaturePolicyPairs& SandboxFlagsWithFeaturePolicies() { DEFINE_STATIC_LOCAL( SandboxFlagFeaturePolicyPairs, array, - ({{kSandboxTopNavigation, mojom::FeaturePolicyFeature::kTopNavigation}, - {kSandboxForms, mojom::FeaturePolicyFeature::kFormSubmission}, - {kSandboxScripts, mojom::FeaturePolicyFeature::kScript}, - {kSandboxPopups, mojom::FeaturePolicyFeature::kPopups}, - {kSandboxPointerLock, mojom::FeaturePolicyFeature::kPointerLock}, - {kSandboxModals, mojom::FeaturePolicyFeature::kModals}, - {kSandboxOrientationLock, + ({{WebSandboxFlags::kTopNavigation, + mojom::FeaturePolicyFeature::kTopNavigation}, + {WebSandboxFlags::kForms, mojom::FeaturePolicyFeature::kFormSubmission}, + {WebSandboxFlags::kScripts, mojom::FeaturePolicyFeature::kScript}, + {WebSandboxFlags::kPopups, mojom::FeaturePolicyFeature::kPopups}, + {WebSandboxFlags::kPointerLock, + mojom::FeaturePolicyFeature::kPointerLock}, + {WebSandboxFlags::kModals, mojom::FeaturePolicyFeature::kModals}, + {WebSandboxFlags::kOrientationLock, mojom::FeaturePolicyFeature::kOrientationLock}, - {kSandboxPresentationController, + {WebSandboxFlags::kPresentationController, mojom::FeaturePolicyFeature::kPresentation}})); return array; } @@ -63,8 +65,8 @@ // are always removed from the set of sandbox flags set for a sandboxed // <iframe> (those sandbox flags are now contained in the |ContainerPolicy|). SandboxFlags SandboxFlagsImplementedByFeaturePolicy() { - DEFINE_STATIC_LOCAL(SandboxFlags, mask, (kSandboxNone)); - if (mask == kSandboxNone) { + DEFINE_STATIC_LOCAL(SandboxFlags, mask, (WebSandboxFlags::kNone)); + if (mask == WebSandboxFlags::kNone) { for (const auto& pair : SandboxFlagsWithFeaturePolicies()) mask |= pair.first; } @@ -75,7 +77,7 @@ String& invalid_tokens_error_message) { // http://www.w3.org/TR/html5/the-iframe-element.html#attr-iframe-sandbox // Parse the unordered set of unique space-separated tokens. - SandboxFlags flags = kSandboxAll; + SandboxFlags flags = WebSandboxFlags::kAll; unsigned length = policy.size(); unsigned number_of_token_errors = 0; StringBuilder token_errors; @@ -84,34 +86,34 @@ // Turn off the corresponding sandbox flag if it's set as "allowed". String sandbox_token(policy[index]); if (EqualIgnoringASCIICase(sandbox_token, "allow-same-origin")) { - flags &= ~kSandboxOrigin; + flags = flags & ~WebSandboxFlags::kOrigin; } else if (EqualIgnoringASCIICase(sandbox_token, "allow-forms")) { - flags &= ~kSandboxForms; + flags = flags & ~WebSandboxFlags::kForms; } else if (EqualIgnoringASCIICase(sandbox_token, "allow-scripts")) { - flags &= ~kSandboxScripts; - flags &= ~kSandboxAutomaticFeatures; + flags = flags & ~WebSandboxFlags::kScripts; + flags = flags & ~WebSandboxFlags::kAutomaticFeatures; } else if (EqualIgnoringASCIICase(sandbox_token, "allow-top-navigation")) { - flags &= ~kSandboxTopNavigation; + flags = flags & ~WebSandboxFlags::kTopNavigation; } else if (EqualIgnoringASCIICase(sandbox_token, "allow-popups")) { - flags &= ~kSandboxPopups; + flags = flags & ~WebSandboxFlags::kPopups; } else if (EqualIgnoringASCIICase(sandbox_token, "allow-pointer-lock")) { - flags &= ~kSandboxPointerLock; + flags = flags & ~WebSandboxFlags::kPointerLock; } else if (EqualIgnoringASCIICase(sandbox_token, "allow-orientation-lock")) { - flags &= ~kSandboxOrientationLock; + flags = flags & ~WebSandboxFlags::kOrientationLock; } else if (EqualIgnoringASCIICase(sandbox_token, "allow-popups-to-escape-sandbox")) { - flags &= ~kSandboxPropagatesToAuxiliaryBrowsingContexts; + flags = flags & ~WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts; } else if (EqualIgnoringASCIICase(sandbox_token, "allow-modals")) { - flags &= ~kSandboxModals; + flags = flags & ~WebSandboxFlags::kModals; } else if (EqualIgnoringASCIICase(sandbox_token, "allow-presentation")) { - flags &= ~kSandboxPresentationController; + flags = flags & ~WebSandboxFlags::kPresentationController; } else if (EqualIgnoringASCIICase( sandbox_token, "allow-top-navigation-by-user-activation")) { - flags &= ~kSandboxTopNavigationByUserActivation; + flags = flags & ~WebSandboxFlags::kTopNavigationByUserActivation; } else if (EqualIgnoringASCIICase( sandbox_token, "allow-downloads-without-user-activation")) { - flags &= ~kSandboxDownloads; + flags = flags & ~WebSandboxFlags::kDownloads; } else { token_errors.Append(token_errors.IsEmpty() ? "'" : ", '"); token_errors.Append(sandbox_token); @@ -142,31 +144,9 @@ SandboxFlags sandbox_flags, ParsedFeaturePolicy& parsed_feature_policy) { for (const auto& pair : SandboxFlagsWithFeaturePolicies()) { - if (sandbox_flags & pair.first) + if ((sandbox_flags & pair.first) != WebSandboxFlags::kNone) DisallowFeatureIfNotPresent(pair.second, parsed_feature_policy); } } -STATIC_ASSERT_ENUM(WebSandboxFlags::kNone, kSandboxNone); -STATIC_ASSERT_ENUM(WebSandboxFlags::kNavigation, kSandboxNavigation); -STATIC_ASSERT_ENUM(WebSandboxFlags::kPlugins, kSandboxPlugins); -STATIC_ASSERT_ENUM(WebSandboxFlags::kOrigin, kSandboxOrigin); -STATIC_ASSERT_ENUM(WebSandboxFlags::kForms, kSandboxForms); -STATIC_ASSERT_ENUM(WebSandboxFlags::kScripts, kSandboxScripts); -STATIC_ASSERT_ENUM(WebSandboxFlags::kTopNavigation, kSandboxTopNavigation); -STATIC_ASSERT_ENUM(WebSandboxFlags::kPopups, kSandboxPopups); -STATIC_ASSERT_ENUM(WebSandboxFlags::kAutomaticFeatures, - kSandboxAutomaticFeatures); -STATIC_ASSERT_ENUM(WebSandboxFlags::kPointerLock, kSandboxPointerLock); -STATIC_ASSERT_ENUM(WebSandboxFlags::kDocumentDomain, kSandboxDocumentDomain); -STATIC_ASSERT_ENUM(WebSandboxFlags::kOrientationLock, kSandboxOrientationLock); -STATIC_ASSERT_ENUM(WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts, - kSandboxPropagatesToAuxiliaryBrowsingContexts); -STATIC_ASSERT_ENUM(WebSandboxFlags::kModals, kSandboxModals); -STATIC_ASSERT_ENUM(WebSandboxFlags::kPresentationController, - kSandboxPresentationController); -STATIC_ASSERT_ENUM(WebSandboxFlags::kTopNavigationByUserActivation, - kSandboxTopNavigationByUserActivation); -STATIC_ASSERT_ENUM(WebSandboxFlags::kDownloads, kSandboxDownloads); - } // namespace blink
diff --git a/third_party/blink/renderer/core/frame/sandbox_flags.h b/third_party/blink/renderer/core/frame/sandbox_flags.h index 59bfc85d..b8689f0 100644 --- a/third_party/blink/renderer/core/frame/sandbox_flags.h +++ b/third_party/blink/renderer/core/frame/sandbox_flags.h
@@ -30,42 +30,15 @@ #include <vector> #include "third_party/blink/public/common/feature_policy/feature_policy.h" +#include "third_party/blink/public/common/frame/sandbox_flags.h" #include "third_party/blink/renderer/core/dom/space_split_string.h" #include "third_party/blink/renderer/platform/wtf/forward.h" namespace blink { -enum SandboxFlag { - // See http://www.whatwg.org/specs/web-apps/current-work/#attr-iframe-sandbox - // for a list of the sandbox flags. - kSandboxNone = 0, - kSandboxNavigation = 1, - kSandboxPlugins = 1 << 1, - kSandboxOrigin = 1 << 2, - kSandboxForms = 1 << 3, - kSandboxScripts = 1 << 4, - kSandboxTopNavigation = 1 << 5, - // See https://www.w3.org/Bugs/Public/show_bug.cgi?id=12393 - kSandboxPopups = 1 << 6, - kSandboxAutomaticFeatures = 1 << 7, - kSandboxPointerLock = 1 << 8, - kSandboxDocumentDomain = 1 << 9, - // See - // https://w3c.github.io/screen-orientation/#dfn-sandboxed-orientation-lock-browsing-context-flag. - kSandboxOrientationLock = 1 << 10, - kSandboxPropagatesToAuxiliaryBrowsingContexts = 1 << 11, - kSandboxModals = 1 << 12, - // See - // https://w3c.github.io/presentation-api/#sandboxing-and-the-allow-presentation-keyword - kSandboxPresentationController = 1 << 13, - // See https://github.com/WICG/interventions/issues/42. - kSandboxTopNavigationByUserActivation = 1 << 14, - // See https://crbug.com/539938 - kSandboxDownloads = 1 << 15, - kSandboxAll = -1 // Mask with all bits set to 1. -}; - -typedef int SandboxFlags; +// TODO(ekaramad): Get rid of these. +using SandboxFlag = WebSandboxFlags; +using SandboxFlags = WebSandboxFlags; SandboxFlags ParseSandboxPolicy(const SpaceSplitString& policy, String& invalid_tokens_error_message);
diff --git a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc index 217c7dc..88268ef 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_control_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_control_element.cc
@@ -216,7 +216,7 @@ static bool ShouldAutofocusOnAttach(const HTMLFormControlElement* element) { if (!element->IsAutofocusable()) return false; - if (element->GetDocument().IsSandboxed(kSandboxAutomaticFeatures)) { + if (element->GetDocument().IsSandboxed(WebSandboxFlags::kAutomaticFeatures)) { // FIXME: This message should be moved off the console once a solution to // https://bugs.webkit.org/show_bug.cgi?id=103274 exists. element->GetDocument().AddConsoleMessage(ConsoleMessage::Create(
diff --git a/third_party/blink/renderer/core/html/forms/html_form_element.cc b/third_party/blink/renderer/core/html/forms/html_form_element.cc index 1497714a..4f8ad23 100644 --- a/third_party/blink/renderer/core/html/forms/html_form_element.cc +++ b/third_party/blink/renderer/core/html/forms/html_form_element.cc
@@ -275,7 +275,7 @@ return; } - if (GetDocument().IsSandboxed(kSandboxForms)) { + if (GetDocument().IsSandboxed(WebSandboxFlags::kForms)) { GetDocument().AddConsoleMessage(ConsoleMessage::Create( mojom::ConsoleMessageSource::kSecurity, mojom::ConsoleMessageLevel::kError, @@ -465,7 +465,7 @@ DCHECK(submission->Form()); if (submission->Action().IsEmpty()) return; - if (GetDocument().IsSandboxed(kSandboxForms)) { + if (GetDocument().IsSandboxed(WebSandboxFlags::kForms)) { // FIXME: This message should be moved off the console once a solution to // https://bugs.webkit.org/show_bug.cgi?id=103274 exists. GetDocument().AddConsoleMessage(ConsoleMessage::Create(
diff --git a/third_party/blink/renderer/core/html/html_anchor_element.cc b/third_party/blink/renderer/core/html/html_anchor_element.cc index d8f2d8f..2db03f4 100644 --- a/third_party/blink/renderer/core/html/html_anchor_element.cc +++ b/third_party/blink/renderer/core/html/html_anchor_element.cc
@@ -406,7 +406,7 @@ kBlockingDownloadsInAdFrameWithoutUserActivation)) return; } - if (GetDocument().IsSandboxed(kSandboxDownloads)) { + if (GetDocument().IsSandboxed(WebSandboxFlags::kDownloads)) { if (!has_gesture) { UseCounter::Count(GetDocument(), WebFeature::kDownloadInSandboxWithoutUserGesture);
diff --git a/third_party/blink/renderer/core/html/html_frame_element_base.cc b/third_party/blink/renderer/core/html/html_frame_element_base.cc index 9124cd0a4..bcd8df0 100644 --- a/third_party/blink/renderer/core/html/html_frame_element_base.cc +++ b/third_party/blink/renderer/core/html/html_frame_element_base.cc
@@ -138,7 +138,7 @@ scoped_refptr<const SecurityOrigin> HTMLFrameElementBase::GetOriginForFeaturePolicy() const { // Sandboxed frames have a unique origin. - if (GetSandboxFlags() & kSandboxOrigin) + if ((GetSandboxFlags() & WebSandboxFlags::kOrigin) != WebSandboxFlags::kNone) return SecurityOrigin::CreateUniqueOpaque(); // If the frame will inherit its origin from the owner, then use the owner's
diff --git a/third_party/blink/renderer/core/html/html_frame_owner_element.cc b/third_party/blink/renderer/core/html/html_frame_owner_element.cc index 682b5a5f2..64eeea9 100644 --- a/third_party/blink/renderer/core/html/html_frame_owner_element.cc +++ b/third_party/blink/renderer/core/html/html_frame_owner_element.cc
@@ -145,7 +145,7 @@ : HTMLElement(tag_name, document), content_frame_(nullptr), embedded_content_view_(nullptr), - sandbox_flags_(kSandboxNone), + sandbox_flags_(WebSandboxFlags::kNone), should_lazy_load_children_(DoesParentAllowLazyLoadingChildren(document)) { }
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc index 06a85f3c..517043c 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.cc +++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
@@ -151,15 +151,15 @@ RuntimeEnabledFeatures::FeaturePolicyForSandboxEnabled(); SandboxFlags current_flags = value.IsNull() - ? kSandboxNone + ? WebSandboxFlags::kNone : ParseSandboxPolicy(sandbox_->TokenSet(), invalid_tokens); // With FeaturePolicyForSandbox, sandbox flags are represented as part of // the container policies. However, not all sandbox flags are yet converted // and for now the residue will stay around in the stored flags. // (see https://crbug.com/812381). SandboxFlags sandbox_to_set = current_flags; - sandbox_flags_converted_to_feature_policies_ = kSandboxNone; - if (feature_policy_for_sandbox && current_flags != kSandboxNone) { + sandbox_flags_converted_to_feature_policies_ = WebSandboxFlags::kNone; + if (feature_policy_for_sandbox && current_flags != WebSandboxFlags::kNone) { // The part of sandbox which will be mapped to feature policies. sandbox_flags_converted_to_feature_policies_ = current_flags; // Residue sandbox which will not be mapped to feature policies. @@ -288,9 +288,10 @@ // If the frame is sandboxed at all, then warn if feature policy attributes // will override the sandbox attributes. // TODO(ekaramad): Add similar messages for all the converted sandbox flags. - if (messages && - (sandbox_flags_converted_to_feature_policies_ & kSandboxNavigation)) { - if (!(sandbox_flags_converted_to_feature_policies_ & kSandboxForms) && + if (messages && (sandbox_flags_converted_to_feature_policies_ & + WebSandboxFlags::kNavigation) != WebSandboxFlags::kNone) { + if ((sandbox_flags_converted_to_feature_policies_ & + WebSandboxFlags::kForms) == WebSandboxFlags::kNone && IsFeatureDeclared(mojom::FeaturePolicyFeature::kFormSubmission, container_policy)) { messages->push_back(
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.h b/third_party/blink/renderer/core/html/html_iframe_element.h index f0b7471..caede62 100644 --- a/third_party/blink/renderer/core/html/html_iframe_element.h +++ b/third_party/blink/renderer/core/html/html_iframe_element.h
@@ -97,7 +97,8 @@ // This represents a subset of sandbox flags set through 'sandbox' attribute // that will be converted to feature policies as part of the container // policies. - SandboxFlags sandbox_flags_converted_to_feature_policies_ = kSandboxNone; + SandboxFlags sandbox_flags_converted_to_feature_policies_ = + WebSandboxFlags::kNone; network::mojom::ReferrerPolicy referrer_policy_; };
diff --git a/third_party/blink/renderer/core/html/html_plugin_element.cc b/third_party/blink/renderer/core/html/html_plugin_element.cc index e87d363..140ee22 100644 --- a/third_party/blink/renderer/core/html/html_plugin_element.cc +++ b/third_party/blink/renderer/core/html/html_plugin_element.cc
@@ -713,7 +713,7 @@ bool HTMLPlugInElement::AllowedToLoadPlugin(const KURL& url, const String& mime_type) { - if (GetDocument().IsSandboxed(kSandboxPlugins)) { + if (GetDocument().IsSandboxed(WebSandboxFlags::kPlugins)) { GetDocument().AddConsoleMessage( ConsoleMessage::Create(mojom::ConsoleMessageSource::kSecurity, mojom::ConsoleMessageLevel::kError,
diff --git a/third_party/blink/renderer/core/html/media/autoplay_policy.cc b/third_party/blink/renderer/core/html/media/autoplay_policy.cc index 77733386..d4545d6 100644 --- a/third_party/blink/renderer/core/html/media/autoplay_policy.cc +++ b/third_party/blink/renderer/core/html/media/autoplay_policy.cc
@@ -399,7 +399,7 @@ } bool AutoplayPolicy::ShouldAutoplay() { - if (element_->GetDocument().IsSandboxed(kSandboxAutomaticFeatures)) + if (element_->GetDocument().IsSandboxed(WebSandboxFlags::kAutomaticFeatures)) return false; return element_->can_autoplay_ && element_->paused_ && element_->Autoplay(); }
diff --git a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc index 0f3a2bc7..71c1b496 100644 --- a/third_party/blink/renderer/core/inspector/inspector_css_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_css_agent.cc
@@ -1958,7 +1958,8 @@ Document* owner_document) { DCHECK(page_style_sheet); - if (!page_style_sheet->ownerNode() && page_style_sheet->href().IsEmpty()) + if (!page_style_sheet->ownerNode() && page_style_sheet->href().IsEmpty() && + !page_style_sheet->IsConstructed()) return protocol::CSS::StyleSheetOriginEnum::UserAgent; if (page_style_sheet->ownerNode() &&
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc index 193d19b..9ff24c3 100644 --- a/third_party/blink/renderer/core/inspector/inspector_network_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.cc
@@ -509,7 +509,7 @@ static std::unique_ptr<protocol::Network::Response> BuildObjectForResourceResponse(const ResourceResponse& response, - Resource* cached_resource = nullptr, + const Resource* cached_resource = nullptr, bool* is_empty = nullptr) { if (response.IsNull()) return nullptr; @@ -920,7 +920,7 @@ uint64_t identifier, DocumentLoader* loader, const ResourceResponse& response, - Resource* cached_resource) { + const Resource* cached_resource) { String request_id = IdentifiersFactory::RequestId(loader, identifier); bool is_not_modified = response.HttpStatusCode() == 304;
diff --git a/third_party/blink/renderer/core/inspector/inspector_network_agent.h b/third_party/blink/renderer/core/inspector/inspector_network_agent.h index b6614057..71244f7 100644 --- a/third_party/blink/renderer/core/inspector/inspector_network_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_network_agent.h
@@ -114,7 +114,7 @@ void DidReceiveResourceResponse(uint64_t identifier, DocumentLoader*, const ResourceResponse&, - Resource*); + const Resource*); void DidReceiveData(uint64_t identifier, DocumentLoader*, const char* data,
diff --git a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc index fd0800fe..7fa1292 100644 --- a/third_party/blink/renderer/core/inspector/inspector_page_agent.cc +++ b/third_party/blink/renderer/core/inspector/inspector_page_agent.cc
@@ -178,7 +178,7 @@ } // namespace -static bool PrepareResourceBuffer(Resource* cached_resource, +static bool PrepareResourceBuffer(const Resource* cached_resource, bool* has_zero_size) { if (!cached_resource) return false; @@ -197,7 +197,7 @@ return true; } -static bool HasTextContent(Resource* cached_resource) { +static bool HasTextContent(const Resource* cached_resource) { ResourceType type = cached_resource->GetType(); return type == ResourceType::kCSSStyleSheet || type == ResourceType::kXSLStyleSheet || @@ -310,7 +310,7 @@ } // static -bool InspectorPageAgent::CachedResourceContent(Resource* cached_resource, +bool InspectorPageAgent::CachedResourceContent(const Resource* cached_resource, String* result, bool* base64_encoded) { bool has_zero_size;
diff --git a/third_party/blink/renderer/core/inspector/inspector_page_agent.h b/third_party/blink/renderer/core/inspector/inspector_page_agent.h index 79d30c96..d7dfd32 100644 --- a/third_party/blink/renderer/core/inspector/inspector_page_agent.h +++ b/third_party/blink/renderer/core/inspector/inspector_page_agent.h
@@ -89,7 +89,7 @@ }; static HeapVector<Member<Document>> ImportsForFrame(LocalFrame*); - static bool CachedResourceContent(Resource*, + static bool CachedResourceContent(const Resource*, String* result, bool* base64_encoded); static bool SharedBufferContent(scoped_refptr<const SharedBuffer>,
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc index 162e924..16bb86e 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.cc +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.cc
@@ -133,7 +133,7 @@ uint64_t identifier, DocumentLoader* loader, const ResourceResponse& response, - Resource*) { + const Resource*) { LocalFrame* frame = loader ? loader->GetFrame() : nullptr; TRACE_EVENT_INSTANT1("devtools.timeline", "ResourceReceiveResponse", TRACE_EVENT_SCOPE_THREAD, "data",
diff --git a/third_party/blink/renderer/core/inspector/inspector_trace_events.h b/third_party/blink/renderer/core/inspector/inspector_trace_events.h index 566e160..978e2af1 100644 --- a/third_party/blink/renderer/core/inspector/inspector_trace_events.h +++ b/third_party/blink/renderer/core/inspector/inspector_trace_events.h
@@ -98,7 +98,7 @@ void DidReceiveResourceResponse(uint64_t identifier, DocumentLoader*, const ResourceResponse&, - Resource*); + const Resource*); void DidReceiveData(uint64_t identifier, DocumentLoader*, const char* data,
diff --git a/third_party/blink/renderer/core/inspector/network_resources_data.cc b/third_party/blink/renderer/core/inspector/network_resources_data.cc index 93c79f1..14a3a4cc95 100644 --- a/third_party/blink/renderer/core/inspector/network_resources_data.cc +++ b/third_party/blink/renderer/core/inspector/network_resources_data.cc
@@ -132,7 +132,7 @@ } void NetworkResourcesData::ResourceData::SetResource( - Resource* cached_resource) { + const Resource* cached_resource) { cached_resource_ = cached_resource; } @@ -329,7 +329,7 @@ } void NetworkResourcesData::AddResource(const String& request_id, - Resource* cached_resource) { + const Resource* cached_resource) { ResourceData* resource_data = ResourceDataForRequestId(request_id); if (!resource_data) return;
diff --git a/third_party/blink/renderer/core/inspector/network_resources_data.h b/third_party/blink/renderer/core/inspector/network_resources_data.h index 7c6e373..a533843 100644 --- a/third_party/blink/renderer/core/inspector/network_resources_data.h +++ b/third_party/blink/renderer/core/inspector/network_resources_data.h
@@ -140,8 +140,8 @@ buffer_ = std::move(buffer); } - Resource* CachedResource() const { return cached_resource_.Get(); } - void SetResource(Resource*); + const Resource* CachedResource() const { return cached_resource_.Get(); } + void SetResource(const Resource*); XHRReplayData* XhrReplayData() const { return xhr_replay_data_.Get(); } void SetXHRReplayData(XHRReplayData* xhr_replay_data) { @@ -201,7 +201,7 @@ int64_t pending_encoded_data_length_; scoped_refptr<SharedBuffer> buffer_; - WeakMember<Resource> cached_resource_; + WeakMember<const Resource> cached_resource_; scoped_refptr<BlobDataHandle> downloaded_file_blob_; Vector<AtomicString> certificate_; scoped_refptr<EncodedFormData> post_data_; @@ -234,7 +234,7 @@ const char* data, uint64_t data_length); void MaybeDecodeDataToContent(const String& request_id); - void AddResource(const String& request_id, Resource*); + void AddResource(const String& request_id, const Resource*); ResourceData const* Data(const String& request_id); void Clear(const String& preserved_loader_id = String());
diff --git a/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc b/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc index 427cece..e532266 100644 --- a/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc +++ b/third_party/blink/renderer/core/layout/flexible_box_algorithm.cc
@@ -489,7 +489,7 @@ // when percentages are involved, so for now don't apply min-height: auto // in such cases. if (IsColumnFlow() && child.IsFlexibleBox() && - ToLayoutBlock(child).HasPercentHeightDescendants()) + To<LayoutBlock>(child).HasPercentHeightDescendants()) return false; return !child.ShouldApplySizeContainment() &&
diff --git a/third_party/blink/renderer/core/layout/layout_block.cc b/third_party/blink/renderer/core/layout/layout_block.cc index 66ebd6d..02f9a1d7 100644 --- a/third_party/blink/renderer/core/layout/layout_block.cc +++ b/third_party/blink/renderer/core/layout/layout_block.cc
@@ -875,7 +875,7 @@ relayout_children || height_available_to_children_changed_; if (!update_child_needs_layout) { if (!positioned_object->IsLayoutNGObject() || - ToLayoutBlock(positioned_object) + To<LayoutBlock>(positioned_object) ->IsLegacyInitiatedOutOfFlowLayout()) { update_child_needs_layout |= NeedsLayoutDueToStaticPosition(positioned_object); @@ -1928,10 +1928,10 @@ first_line_block->IsFloatingOrOutOfFlowPositioned() || !parent_block || !parent_block->BehavesLikeBlockContainer()) break; - SECURITY_DCHECK(parent_block->IsLayoutBlock()); - if (ToLayoutBlock(parent_block)->FirstChild() != first_line_block) + auto* parent_layout_block = DynamicTo<LayoutBlock>(parent_block); + if (parent_layout_block->FirstChild() != first_line_block) break; - first_line_block = ToLayoutBlock(parent_block); + first_line_block = parent_layout_block; } if (!has_pseudo) @@ -1946,7 +1946,7 @@ for (LayoutObject* child = FirstChild(); child && !child->IsFloatingOrOutOfFlowPositioned() && child->IsLayoutBlockFlow(); - child = ToLayoutBlock(child)->FirstChild()) { + child = To<LayoutBlock>(child)->FirstChild()) { if (child->ChildrenInline()) return ToLayoutBlockFlow(child); } @@ -2058,16 +2058,17 @@ bool LayoutBlock::HasMarginBeforeQuirk(const LayoutBox* child) const { // If the child has the same directionality as we do, then we can just return // its margin quirk. + auto* child_layout_block = DynamicTo<LayoutBlock>(child); if (!child->IsWritingModeRoot()) { - return child->IsLayoutBlock() ? ToLayoutBlock(child)->HasMarginBeforeQuirk() - : child->StyleRef().HasMarginBeforeQuirk(); + return child_layout_block ? child_layout_block->HasMarginBeforeQuirk() + : child->StyleRef().HasMarginBeforeQuirk(); } // The child has a different directionality. If the child is parallel, then // it's just flipped relative to us. We can use the opposite edge. if (child->IsHorizontalWritingMode() == IsHorizontalWritingMode()) { - return child->IsLayoutBlock() ? ToLayoutBlock(child)->HasMarginAfterQuirk() - : child->StyleRef().HasMarginAfterQuirk(); + return child_layout_block ? child_layout_block->HasMarginAfterQuirk() + : child->StyleRef().HasMarginAfterQuirk(); } // The child is perpendicular to us and box sides are never quirky in @@ -2079,16 +2080,17 @@ bool LayoutBlock::HasMarginAfterQuirk(const LayoutBox* child) const { // If the child has the same directionality as we do, then we can just return // its margin quirk. + auto* child_layout_block = DynamicTo<LayoutBlock>(child); if (!child->IsWritingModeRoot()) { - return child->IsLayoutBlock() ? ToLayoutBlock(child)->HasMarginAfterQuirk() - : child->StyleRef().HasMarginAfterQuirk(); + return child_layout_block ? child_layout_block->HasMarginAfterQuirk() + : child->StyleRef().HasMarginAfterQuirk(); } // The child has a different directionality. If the child is parallel, then // it's just flipped relative to us. We can use the opposite edge. if (child->IsHorizontalWritingMode() == IsHorizontalWritingMode()) { - return child->IsLayoutBlock() ? ToLayoutBlock(child)->HasMarginBeforeQuirk() - : child->StyleRef().HasMarginBeforeQuirk(); + return child_layout_block ? child_layout_block->HasMarginBeforeQuirk() + : child->StyleRef().HasMarginBeforeQuirk(); } // The child is perpendicular to us and box sides are never quirky in
diff --git a/third_party/blink/renderer/core/layout/layout_block.h b/third_party/blink/renderer/core/layout/layout_block.h index aa9a33e..1658619 100644 --- a/third_party/blink/renderer/core/layout/layout_block.h +++ b/third_party/blink/renderer/core/layout/layout_block.h
@@ -27,6 +27,7 @@ #include <memory> #include "third_party/blink/renderer/core/core_export.h" #include "third_party/blink/renderer/core/layout/layout_box.h" +#include "third_party/blink/renderer/platform/wtf/casting.h" #include "third_party/blink/renderer/platform/wtf/list_hash_set.h" namespace blink { @@ -595,6 +596,13 @@ DEFINE_LAYOUT_OBJECT_TYPE_CASTS(LayoutBlock, IsLayoutBlock()); +template <> +struct DowncastTraits<LayoutBlock> { + static bool AllowFrom(const LayoutObject& object) { + return object.IsLayoutBlock(); + } +}; + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_CORE_LAYOUT_LAYOUT_BLOCK_H_
diff --git a/third_party/blink/renderer/core/layout/layout_block_flow.cc b/third_party/blink/renderer/core/layout/layout_block_flow.cc index cba8982..f0298d4 100644 --- a/third_party/blink/renderer/core/layout/layout_block_flow.cc +++ b/third_party/blink/renderer/core/layout/layout_block_flow.cc
@@ -1394,8 +1394,9 @@ LayoutBlockFlow* parent_block_flow = ToLayoutBlockFlow(Parent()); bool sibling_float_may_intrude = false; LayoutObject* prev = PreviousSibling(); - while (prev && (!prev->IsBox() || !prev->IsLayoutBlock() || - ToLayoutBlock(prev)->CreatesNewFormattingContext())) { + auto* prev_layout_block = DynamicTo<LayoutBlock>(prev); + while (prev && (!prev->IsBox() || !prev_layout_block || + prev_layout_block->CreatesNewFormattingContext())) { if (prev->IsFloating()) sibling_float_may_intrude = true; prev = prev->PreviousSibling(); @@ -1409,7 +1410,7 @@ bool parent_floats_may_intrude = !sibling_float_may_intrude && (!prev || ToLayoutBlockFlow(prev)->IsSelfCollapsingBlock() || - ToLayoutBlock(prev)->LogicalTop() > LogicalTop()) && + prev_layout_block->LogicalTop() > LogicalTop()) && parent_block_flow->LowestFloatLogicalBottom() > LogicalTop(); if (sibling_float_may_intrude || parent_floats_may_intrude) AddIntrudingFloats(parent_block_flow, @@ -2165,8 +2166,8 @@ // we're looking at current values. if (grandchild_box->NeedsLayout()) { grandchild_box->ComputeAndSetBlockDirectionMargins(this); - if (grandchild_box->IsLayoutBlock()) { - LayoutBlock* grandchild_block = ToLayoutBlock(grandchild_box); + auto* grandchild_block = DynamicTo<LayoutBlock>(grandchild_box); + if (grandchild_block) { grandchild_block->SetHasMarginBeforeQuirk( grandchild_box->StyleRef().HasMarginBeforeQuirk()); grandchild_block->SetHasMarginAfterQuirk( @@ -3194,10 +3195,9 @@ // insertion in a way that isn't sufficient for us, and can only cause trouble // at this point. LayoutBox::AddChild(new_child, before_child); - - if (made_boxes_non_inline && Parent() && IsAnonymousBlock() && - Parent()->IsLayoutBlock()) { - ToLayoutBlock(Parent())->RemoveLeftoverAnonymousBlock(this); + auto* parent_layout_block = DynamicTo<LayoutBlock>(Parent()); + if (made_boxes_non_inline && IsAnonymousBlock() && parent_layout_block) { + parent_layout_block->RemoveLeftoverAnonymousBlock(this); // |this| may be dead now. } } @@ -3611,8 +3611,9 @@ void LayoutBlockFlow::ChildBecameNonInline(LayoutObject*) { MakeChildrenNonInline(); - if (IsAnonymousBlock() && Parent() && Parent()->IsLayoutBlock()) - ToLayoutBlock(Parent())->RemoveLeftoverAnonymousBlock(this); + auto* parent_layout_block = DynamicTo<LayoutBlock>(Parent()); + if (IsAnonymousBlock() && parent_layout_block) + parent_layout_block->RemoveLeftoverAnonymousBlock(this); // |this| may be dead here } @@ -4611,9 +4612,10 @@ children_layout_overflow_changed = true; // TODO(chrishtr): should this be IsBox()? Non-blocks can be // inline and have line box wrappers. - if (layout_object->IsLayoutBlock()) { + auto* layout_block_object = DynamicTo<LayoutBlock>(layout_object); + if (layout_block_object) { if (InlineBox* inline_box_wrapper = - ToLayoutBlock(layout_object)->InlineBoxWrapper()) + layout_block_object->InlineBoxWrapper()) line_boxes.insert(&inline_box_wrapper->Root()); } }
diff --git a/third_party/blink/renderer/core/layout/layout_box.cc b/third_party/blink/renderer/core/layout/layout_box.cc index 99e86f50..525e0cf 100644 --- a/third_party/blink/renderer/core/layout/layout_box.cc +++ b/third_party/blink/renderer/core/layout/layout_box.cc
@@ -3887,8 +3887,8 @@ bool has_perpendicular_containing_block = cb->IsHorizontalWritingMode() != IsHorizontalWritingMode(); LayoutUnit stretched_height(-1); - if (cb->IsLayoutBlock()) { - LayoutBlock* block = ToLayoutBlock(cb); + auto* block = DynamicTo<LayoutBlock>(cb); + if (block) { block->AddPercentHeightDescendant(const_cast<LayoutBox*>(this)); if (block->IsFlexItem()) { const LayoutFlexibleBox* flex_box = @@ -3933,7 +3933,7 @@ logical_height, available_height - BorderAndPaddingLogicalHeight()); } - ToLayoutBlock(cb)->AddPercentHeightDescendant( + To<LayoutBlock>(cb)->AddPercentHeightDescendant( const_cast<LayoutBox*>(this)); cb = cb->ContainingBlock(); } @@ -4026,10 +4026,11 @@ // FIXME: Check logicalTop/logicalBottom here to correctly handle vertical // writing-mode. // https://bugs.webkit.org/show_bug.cgi?id=46500 - if (IsLayoutBlock() && IsOutOfFlowPositioned() && + auto* curr_layout_block = DynamicTo<LayoutBlock>(this); + if (curr_layout_block && IsOutOfFlowPositioned() && StyleRef().Height().IsAuto() && !(StyleRef().Top().IsAuto() || StyleRef().Bottom().IsAuto())) { - LayoutBlock* block = const_cast<LayoutBlock*>(ToLayoutBlock(this)); + LayoutBlock* block = const_cast<LayoutBlock*>(curr_layout_block); LogicalExtentComputedValues computed_values; block->ComputeLogicalHeight(block->LogicalHeight(), LayoutUnit(), computed_values);
diff --git a/third_party/blink/renderer/core/layout/layout_box_model_object.cc b/third_party/blink/renderer/core/layout/layout_box_model_object.cc index be5c65d..c73402e 100644 --- a/third_party/blink/renderer/core/layout/layout_box_model_object.cc +++ b/third_party/blink/renderer/core/layout/layout_box_model_object.cc
@@ -1375,7 +1375,7 @@ // moves (!fullRemoveInsert) so the positioned layoutObject maps don't become // stale. It would be too slow to do the map lookup on each call. DCHECK(!full_remove_insert || !IsLayoutBlock() || - !ToLayoutBlock(this)->HasPositionedObjects()); + !To<LayoutBlock>(this)->HasPositionedObjects()); DCHECK_EQ(this, child->Parent()); DCHECK(!before_child || to_box_model_object == before_child->Parent()); @@ -1418,8 +1418,8 @@ // This condition is rarely hit since this function is usually called on // anonymous blocks which can no longer carry positioned objects (see r120761) // or when fullRemoveInsert is false. - if (full_remove_insert && IsLayoutBlock()) { - LayoutBlock* block = ToLayoutBlock(this); + auto* block = DynamicTo<LayoutBlock>(this); + if (full_remove_insert && block) { block->RemovePositionedObjects(nullptr); block->RemoveFromPercentHeightContainer(); if (block->IsLayoutBlockFlow())
diff --git a/third_party/blink/renderer/core/layout/layout_fieldset.cc b/third_party/blink/renderer/core/layout/layout_fieldset.cc index f0c42eb..91dba64 100644 --- a/third_party/blink/renderer/core/layout/layout_fieldset.cc +++ b/third_party/blink/renderer/core/layout/layout_fieldset.cc
@@ -146,7 +146,7 @@ if (fieldset.IsLayoutNGFieldset()) { // If there is a rendered legend, it will be found inside the anonymous // fieldset wrapper. - parent = ToLayoutBlock(fieldset.FirstChild()); + parent = To<LayoutBlock>(fieldset.FirstChild()); if (!parent) return nullptr; }
diff --git a/third_party/blink/renderer/core/layout/layout_flexible_box.cc b/third_party/blink/renderer/core/layout/layout_flexible_box.cc index 40674ea..d7ead52f 100644 --- a/third_party/blink/renderer/core/layout/layout_flexible_box.cc +++ b/third_party/blink/renderer/core/layout/layout_flexible_box.cc
@@ -1434,8 +1434,9 @@ relayout_children && !relaid_out_children_.Contains(child); // TODO(dgrogan): Broaden the NG part of this check once NG types other // than Mixin derivatives are cached. - if (child->IsLayoutBlock() && - ToLayoutBlock(*child).HasPercentHeightDescendants() && + auto* child_layout_block = DynamicTo<LayoutBlock>(child); + if (child_layout_block && + child_layout_block->HasPercentHeightDescendants() && !CanAvoidLayoutForNGChild(*child)) { // Have to force another relayout even though the child is sized // correctly, because its descendants are not sized correctly yet. Our @@ -1637,8 +1638,8 @@ // https://webkit.org/b/87905. bool child_needs_relayout = flex_item.cross_axis_size != child.LogicalHeight(); - if (child.IsLayoutBlock() && - ToLayoutBlock(child).HasPercentHeightDescendants() && + auto* child_block = DynamicTo<LayoutBlock>(child); + if (child_block && child_block->HasPercentHeightDescendants() && !CanAvoidLayoutForNGChild(child)) { // Have to force another relayout even though the child is sized // correctly, because its descendants are not sized correctly yet. Our
diff --git a/third_party/blink/renderer/core/layout/layout_list_item.cc b/third_party/blink/renderer/core/layout/layout_list_item.cc index 68020a82..4835bc8 100644 --- a/third_party/blink/renderer/core/layout/layout_list_item.cc +++ b/third_party/blink/renderer/core/layout/layout_list_item.cc
@@ -522,10 +522,11 @@ bool found_self_painting_layer = false; do { object = object->ParentBox(); - if (object->IsLayoutBlock()) { + auto* layout_block_object = DynamicTo<LayoutBlock>(object); + if (layout_block_object) { if (!found_self_painting_layer) - ToLayoutBlock(object)->AddContentsVisualOverflow(marker_rect); - ToLayoutBlock(object)->AddLayoutOverflow(marker_rect); + layout_block_object->AddContentsVisualOverflow(marker_rect); + layout_block_object->AddLayoutOverflow(marker_rect); } if (object->HasOverflowClip())
diff --git a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc index 31e226b..7049960a 100644 --- a/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc +++ b/third_party/blink/renderer/core/layout/layout_multi_column_flow_thread.cc
@@ -1343,15 +1343,14 @@ ColumnGap(*multicol_style, LayoutUnit())); if (MultiColumnBlockFlow()->ShouldApplySizeContainment()) { - LayoutUnit size = gap_extra; - if (!multicol_style->HasAutoColumnWidth()) - size += LayoutUnit(multicol_style->ColumnWidth()) * column_count; - max_preferred_logical_width_ = min_preferred_logical_width_ = size; + min_preferred_logical_width_ = max_preferred_logical_width_ = LayoutUnit(); ClearPreferredLogicalWidthsDirty(); - return; + } else { + // Calculate and set new min_preferred_logical_width_ and + // max_preferred_logical_width_. + LayoutFlowThread::ComputePreferredLogicalWidths(); } - LayoutFlowThread::ComputePreferredLogicalWidths(); LayoutUnit column_width; if (multicol_style->HasAutoColumnWidth()) { min_preferred_logical_width_ =
diff --git a/third_party/blink/renderer/core/layout/layout_object.cc b/third_party/blink/renderer/core/layout/layout_object.cc index 12561842..b8659aed 100644 --- a/third_party/blink/renderer/core/layout/layout_object.cc +++ b/third_party/blink/renderer/core/layout/layout_object.cc
@@ -153,10 +153,7 @@ while (container && container->IsAnonymousBlock()) container = container->ContainingBlock(skip_info); - if (!container || !container->IsLayoutBlock()) - return nullptr; // This can still happen in case of an orphaned tree - - return ToLayoutBlock(container); + return DynamicTo<LayoutBlock>(container); } } // namespace @@ -515,9 +512,9 @@ if (parent->IsAnonymous() && parent->Parent()->IsLayoutNGFieldset()) parent = parent->Parent(); } - return parent && parent->IsLayoutBlock() && - IsHTMLFieldSetElement(parent->GetNode()) && - LayoutFieldset::FindInFlowLegend(*ToLayoutBlock(parent)) == this; + const auto* parent_layout_block = DynamicTo<LayoutBlock>(parent); + return parent_layout_block && IsHTMLFieldSetElement(parent->GetNode()) && + LayoutFieldset::FindInFlowLegend(*parent_layout_block) == this; } LayoutObject* LayoutObject::NextInPreOrderAfterChildren() const { @@ -1070,8 +1067,9 @@ void LayoutObject::CheckBlockPositionedObjectsNeedLayout() { DCHECK(!NeedsLayout()); - if (IsLayoutBlock()) - ToLayoutBlock(this)->CheckPositionedObjectsNeedLayout(); + auto* layout_block = DynamicTo<LayoutBlock>(this); + if (layout_block) + layout_block->CheckPositionedObjectsNeedLayout(); } #endif @@ -1163,9 +1161,8 @@ } const LayoutBlock* LayoutObject::InclusiveContainingBlock() const { - if (IsLayoutBlock()) - return ToLayoutBlock(this); - return ContainingBlock(); + auto* layout_block = DynamicTo<LayoutBlock>(this); + return layout_block ? layout_block : ContainingBlock(); } LayoutBlock* LayoutObject::ContainingBlock(AncestorSkipInfo* skip_info) const { @@ -1190,10 +1187,7 @@ } } - if (!object || !object->IsLayoutBlock()) - return nullptr; // This can still happen in case of an orphaned tree - - return ToLayoutBlock(object); + return DynamicTo<LayoutBlock>(object); } FloatRect LayoutObject::AbsoluteBoundingBoxFloatRect( @@ -1990,7 +1984,7 @@ } else { // An anonymous block must be made to wrap this inline. LayoutBlock* block = - ToLayoutBlock(object->Parent())->CreateAnonymousBlock(); + To<LayoutBlock>(object->Parent())->CreateAnonymousBlock(); LayoutObjectChildList* childlist = object->Parent()->VirtualChildren(); childlist->InsertChildNode(object->Parent(), block, object); block->Children()->AppendChildNode( @@ -2421,13 +2415,11 @@ LayoutObject* object = Parent(); Element* viewport_defining_element = GetDocument().ViewportDefiningElement(); while (object) { - if (object->IsLayoutBlock()) { - LayoutBlock* block = ToLayoutBlock(object); - if (block->HasOverflowClip() || - block->GetNode() == viewport_defining_element) { - block->SetScrollAnchorDisablingStyleChanged(true); - return; - } + auto* block = DynamicTo<LayoutBlock>(object); + if (block && (block->HasOverflowClip() || + block->GetNode() == viewport_defining_element)) { + block->SetScrollAnchorDisablingStyleChanged(true); + return; } object = object->Parent(); } @@ -2536,7 +2528,7 @@ if (BehavesLikeBlockContainer() && (diff.NeedsFullPaintInvalidation() || diff.TextDecorationOrColorChanged())) { if (auto* first_line_container = - ToLayoutBlock(this)->NearestInnerBlockWithFirstLine()) + To<LayoutBlock>(this)->NearestInnerBlockWithFirstLine()) first_line_container->SetShouldDoFullPaintInvalidationForFirstLine(); } @@ -3555,7 +3547,7 @@ if (layout_object_for_first_line_style->BehavesLikeBlockContainer()) { if (const LayoutBlock* first_line_block = - ToLayoutBlock(layout_object_for_first_line_style) + To<LayoutBlock>(layout_object_for_first_line_style) ->EnclosingFirstLineStyleBlock()) { if (type == kCached) return first_line_block->GetCachedPseudoStyle(kPseudoIdFirstLine, @@ -4107,7 +4099,7 @@ // not a block, we need to get the selection state from the containing block // to tell if we have any selected node children. LayoutBlock* block = - IsLayoutBlock() ? ToLayoutBlock(this) : ContainingBlock(); + IsLayoutBlock() ? To<LayoutBlock>(this) : ContainingBlock(); if (!block) return; if (!block->IsSelected())
diff --git a/third_party/blink/renderer/core/layout/layout_object_test.cc b/third_party/blink/renderer/core/layout/layout_object_test.cc index 8076911..c4d21205 100644 --- a/third_party/blink/renderer/core/layout/layout_object_test.cc +++ b/third_party/blink/renderer/core/layout/layout_object_test.cc
@@ -242,7 +242,7 @@ LayoutObject* overflow_clip_object = GetLayoutObjectByElementId("overflow-clip-layer"); - LayoutBlock* columns = ToLayoutBlock(GetLayoutObjectByElementId("columns")); + LayoutBlock* columns = To<LayoutBlock>(GetLayoutObjectByElementId("columns")); EXPECT_EQ(columns->Layer(), overflow_clip_object->PaintingLayer()); }
diff --git a/third_party/blink/renderer/core/layout/layout_ruby_base.cc b/third_party/blink/renderer/core/layout/layout_ruby_base.cc index c6e45b4..3ce97f4a 100644 --- a/third_party/blink/renderer/core/layout/layout_ruby_base.cc +++ b/third_party/blink/renderer/core/layout/layout_ruby_base.cc
@@ -89,7 +89,7 @@ LayoutObject* last_child = to_base->LastChild(); if (last_child && last_child->IsAnonymousBlock() && last_child->ChildrenInline()) { - to_block = ToLayoutBlock(last_child); + to_block = To<LayoutBlock>(last_child); } else { to_block = to_base->CreateAnonymousBlock(); to_base->Children()->AppendChildNode(to_base, to_block);
diff --git a/third_party/blink/renderer/core/layout/layout_scrollbar.cc b/third_party/blink/renderer/core/layout/layout_scrollbar.cc index 16c939e0..5f7d9854 100644 --- a/third_party/blink/renderer/core/layout/layout_scrollbar.cc +++ b/third_party/blink/renderer/core/layout/layout_scrollbar.cc
@@ -190,8 +190,9 @@ IntRect(Location(), IntSize(is_horizontal ? Width() : new_thickness, is_horizontal ? new_thickness : Height()))); if (LayoutBox* box = GetScrollableArea()->GetLayoutBox()) { - if (box->IsLayoutBlock()) - ToLayoutBlock(box)->NotifyScrollbarThicknessChanged(); + auto* layout_block = DynamicTo<LayoutBlock>(box); + if (layout_block) + layout_block->NotifyScrollbarThicknessChanged(); box->SetChildNeedsLayout(); // LayoutNG may attempt to reuse line-box fragments. It will do this even // if the |LayoutObject::ChildNeedsLayout| is true (set above).
diff --git a/third_party/blink/renderer/core/layout/layout_table_cell_test.cc b/third_party/blink/renderer/core/layout/layout_table_cell_test.cc index cc6f7c7..a628cb92 100644 --- a/third_party/blink/renderer/core/layout/layout_table_cell_test.cc +++ b/third_party/blink/renderer/core/layout/layout_table_cell_test.cc
@@ -142,7 +142,7 @@ UpdateAllLifecyclePhasesForTest(); // Check that overflow was calculated on the cell. - auto* input_block = ToLayoutBlock(cell->GetLayoutObject()); + auto* input_block = To<LayoutBlock>(cell->GetLayoutObject()); LayoutRect rect = input_block->LocalVisualRect(); EXPECT_EQ(LayoutRect(-1, -1, 24, 24), rect); }
diff --git a/third_party/blink/renderer/core/layout/layout_text_control.cc b/third_party/blink/renderer/core/layout/layout_text_control.cc index 12a3c45..d30a5332 100644 --- a/third_party/blink/renderer/core/layout/layout_text_control.cc +++ b/third_party/blink/renderer/core/layout/layout_text_control.cc
@@ -53,7 +53,7 @@ if (!inner_editor) return; LayoutBlock* inner_editor_layout_object = - ToLayoutBlock(inner_editor->GetLayoutObject()); + To<LayoutBlock>(inner_editor->GetLayoutObject()); if (inner_editor_layout_object) { inner_editor->SetNeedsStyleRecalc( kSubtreeStyleChange, @@ -334,7 +334,7 @@ return LayoutUnit(-1); LayoutBlock* inner_editor_layout_object = - ToLayoutBlock(inner_editor->GetLayoutObject()); + To<LayoutBlock>(inner_editor->GetLayoutObject()); const SimpleFontData* font_data = inner_editor_layout_object->Style(true)->GetFont().PrimaryFont(); DCHECK(font_data);
diff --git a/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc b/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc index 78e976c0..98179479 100644 --- a/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc +++ b/third_party/blink/renderer/core/layout/ng/layout_ng_fieldset.cc
@@ -15,7 +15,7 @@ void LayoutNGFieldset::AddChild(LayoutObject* new_child, LayoutObject* before_child) { - LayoutBlock* fieldset_content = ToLayoutBlock(FirstChild()); + LayoutBlock* fieldset_content = To<LayoutBlock>(FirstChild()); if (!fieldset_content) { // We wrap everything inside an anonymous child, which will take care of the // fieldset contents. This parent will only be responsible for the fieldset
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 75f72d4..f74eb42 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
@@ -288,13 +288,11 @@ } void NGBlockNode::PrepareForLayout() { - if (box_->IsLayoutBlock()) { - LayoutBlock* block = ToLayoutBlock(box_); - if (block->HasOverflowClip()) { - DCHECK(block->GetScrollableArea()); - if (block->GetScrollableArea()->ShouldPerformScrollAnchoring()) - block->GetScrollableArea()->GetScrollAnchor()->NotifyBeforeLayout(); - } + auto* block = DynamicTo<LayoutBlock>(box_); + if (block && block->HasOverflowClip()) { + DCHECK(block->GetScrollableArea()); + if (block->GetScrollableArea()->ShouldPerformScrollAnchoring()) + block->GetScrollableArea()->GetScrollAnchor()->NotifyBeforeLayout(); } // TODO(layoutng) Can UpdateMarkerTextIfNeeded call be moved @@ -485,7 +483,7 @@ } NGLayoutInputNode NGBlockNode::FirstChild() const { - auto* block = ToLayoutBlock(box_); + auto* block = To<LayoutBlock>(box_); auto* child = GetLayoutObjectForFirstChildNode(block); if (!child) return nullptr; @@ -497,13 +495,13 @@ NGBlockNode NGBlockNode::GetRenderedLegend() const { if (!IsFieldsetContainer()) return nullptr; - return NGBlockNode(LayoutFieldset::FindInFlowLegend(*ToLayoutBlock(box_))); + return NGBlockNode(LayoutFieldset::FindInFlowLegend(*To<LayoutBlock>(box_))); } NGBlockNode NGBlockNode::GetFieldsetContent() const { if (!IsFieldsetContainer()) return nullptr; - auto* child = GetLayoutObjectForFirstChildNode(ToLayoutBlock(box_)); + auto* child = GetLayoutObjectForFirstChildNode(To<LayoutBlock>(box_)); if (!child) return nullptr; return NGBlockNode(ToLayoutBox(child)); @@ -602,7 +600,7 @@ offset_from_start); } - LayoutBlock* block = ToLayoutBlockOrNull(box_); + LayoutBlock* block = DynamicTo<LayoutBlock>(box_); if (LIKELY(block && IsLastFragment(physical_fragment))) { LayoutUnit intrinsic_block_size = layout_result.IntrinsicBlockSize(); if (UNLIKELY(constraint_space.HasBlockFragmentation())) { @@ -792,10 +790,9 @@ } bool NGBlockNode::UseLogicalBottomMarginEdgeForInlineBlockBaseline() const { - LayoutBox* layout_box = GetLayoutBox(); - return layout_box->IsLayoutBlock() && - ToLayoutBlock(layout_box) - ->UseLogicalBottomMarginEdgeForInlineBlockBaseline(); + auto* layout_box = DynamicTo<LayoutBlock>(GetLayoutBox()); + return layout_box && + layout_box->UseLogicalBottomMarginEdgeForInlineBlockBaseline(); } scoped_refptr<const NGLayoutResult> NGBlockNode::LayoutAtomicInline( @@ -840,7 +837,7 @@ // we need to be at a formatting context boundary, since NG and legacy don't // cooperate on e.g. margin collapsing. DCHECK(!box_->IsLayoutBlock() || - ToLayoutBlock(box_)->CreatesNewFormattingContext()); + To<LayoutBlock>(box_)->CreatesNewFormattingContext()); scoped_refptr<const NGLayoutResult> layout_result = box_->GetCachedLayoutResult();
diff --git a/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc b/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc index 3b5e8e0..a66cb62 100644 --- a/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc +++ b/third_party/blink/renderer/core/loader/appcache/application_cache_host.cc
@@ -134,7 +134,7 @@ LocalFrame* frame = document_loader_->GetFrame(); Document* document = frame->GetDocument(); - if (document->IsSandboxed(kSandboxOrigin)) { + if (document->IsSandboxed(WebSandboxFlags::kOrigin)) { // Prevent sandboxes from establishing application caches. SelectCacheWithoutManifest(); return;
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 23310e60..32ad63e 100644 --- a/third_party/blink/renderer/core/loader/base_fetch_context.cc +++ b/third_party/blink/renderer/core/loader/base_fetch_context.cc
@@ -173,11 +173,11 @@ } } - request.AddHttpHeaderField("Sec-Fetch-Dest", destination_value); - request.AddHttpHeaderField( + request.SetHttpHeaderField("Sec-Fetch-Dest", destination_value); + request.SetHttpHeaderField( "Sec-Fetch-Mode", FetchRequestModeToString(request.GetFetchRequestMode())); - request.AddHttpHeaderField("Sec-Fetch-Site", site_value); + request.SetHttpHeaderField("Sec-Fetch-Site", site_value); // We don't set `Sec-Fetch-User` for subresource requests. } }
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc index 8a9ad38..c3cf805 100644 --- a/third_party/blink/renderer/core/loader/frame_loader.cc +++ b/third_party/blink/renderer/core/loader/frame_loader.cc
@@ -192,7 +192,7 @@ : frame_(frame), progress_tracker_(MakeGarbageCollected<ProgressTracker>(frame)), in_restore_scroll_(false), - forced_sandbox_flags_(kSandboxNone), + forced_sandbox_flags_(WebSandboxFlags::kNone), dispatching_did_clear_window_object_in_main_world_(false), detached_(false), virtual_time_pauser_( @@ -713,7 +713,9 @@ if (!javascript_url_is_allowed) return false; - if (frame_->Owner() && frame_->Owner()->GetSandboxFlags() & kSandboxOrigin) + if (frame_->Owner() && + ((frame_->Owner()->GetSandboxFlags() & WebSandboxFlags::kOrigin) != + WebSandboxFlags::kNone)) return false; frame_->GetDocument()->ProcessJavaScriptUrl( @@ -1526,7 +1528,8 @@ // be considered when deciding whether to reuse it. // Spec: // https://html.spec.whatwg.org/C/#initialise-the-document-object - if (csp && (csp->GetSandboxMask() & kSandboxOrigin)) { + if (csp && (csp->GetSandboxMask() & WebSandboxFlags::kOrigin) != + WebSandboxFlags::kNone) { return false; }
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc index a6c2965..ff28994 100644 --- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc +++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.cc
@@ -62,7 +62,7 @@ uint64_t identifier, const ResourceRequest& request, const ResourceResponse& response, - Resource* resource, + const Resource* resource, ResponseSource response_source) { LocalFrame& frame = frame_or_imported_document_->GetFrame(); DocumentLoader& document_loader =
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h index 91bc2af..8558965 100644 --- a/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h +++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_frame.h
@@ -36,7 +36,7 @@ void DidReceiveResponse(uint64_t identifier, const ResourceRequest& request, const ResourceResponse& response, - Resource* resource, + const Resource* resource, ResponseSource) override; void DidReceiveData(uint64_t identifier, base::span<const char> chunk) override;
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc index d38e0b0..fe031bd9 100644 --- a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc +++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.cc
@@ -40,7 +40,7 @@ uint64_t identifier, const ResourceRequest& request, const ResourceResponse& response, - Resource* resource, + const Resource* resource, ResponseSource) { if (response.HasMajorCertificateErrors()) { WebMixedContentContextType context_type =
diff --git a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h index 262327b..59a2329 100644 --- a/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h +++ b/third_party/blink/renderer/core/loader/resource_load_observer_for_worker.h
@@ -33,7 +33,7 @@ void DidReceiveResponse(uint64_t identifier, const ResourceRequest& request, const ResourceResponse& response, - Resource* resource, + const Resource* resource, ResponseSource) override; void DidReceiveData(uint64_t identifier, base::span<const char> chunk) override;
diff --git a/third_party/blink/renderer/core/page/chrome_client.cc b/third_party/blink/renderer/core/page/chrome_client.cc index 8bf9ac4..ef95959 100644 --- a/third_party/blink/renderer/core/page/chrome_client.cc +++ b/third_party/blink/renderer/core/page/chrome_client.cc
@@ -256,7 +256,7 @@ return false; } - if (frame->GetDocument()->IsSandboxed(kSandboxModals)) { + if (frame->GetDocument()->IsSandboxed(WebSandboxFlags::kModals)) { UseCounter::Count(frame->GetDocument(), WebFeature::kDialogInSandboxedContext); frame->Console().AddMessage(ConsoleMessage::Create(
diff --git a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc index 1814c9f..7ba626a 100644 --- a/third_party/blink/renderer/core/page/chrome_client_impl_test.cc +++ b/third_party/blink/renderer/core/page/chrome_client_impl_test.cc
@@ -95,7 +95,7 @@ request.SetNavigationPolicy(kNavigationPolicyNewForegroundTab); WebWindowFeatures features; EXPECT_EQ(nullptr, chrome_client_impl_->CreateWindow( - frame, request, features, kSandboxNone, + frame, request, features, WebSandboxFlags::kNone, FeaturePolicy::FeatureState(), "")); }
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc index c6ec294..dab84de 100644 --- a/third_party/blink/renderer/core/page/create_window.cc +++ b/third_party/blink/renderer/core/page/create_window.cc
@@ -240,7 +240,7 @@ LocalFrame::HasTransientUserActivation(&opener_frame)); // Sandboxed frames cannot open new auxiliary browsing contexts. - if (opener_frame.GetDocument()->IsSandboxed(kSandboxPopups)) { + if (opener_frame.GetDocument()->IsSandboxed(WebSandboxFlags::kPopups)) { // FIXME: This message should be moved off the console once a solution to // https://bugs.webkit.org/show_bug.cgi?id=103274 exists. opener_frame.GetDocument()->AddConsoleMessage(ConsoleMessage::Create( @@ -253,12 +253,12 @@ } bool propagate_sandbox = opener_frame.GetDocument()->IsSandboxed( - kSandboxPropagatesToAuxiliaryBrowsingContexts); + WebSandboxFlags::kPropagatesToAuxiliaryBrowsingContexts); const SandboxFlags sandbox_flags = propagate_sandbox ? opener_frame.GetDocument()->GetSandboxFlags() - : kSandboxNone; + : WebSandboxFlags::kNone; bool not_sandboxed = - opener_frame.GetDocument()->GetSandboxFlags() == kSandboxNone; + opener_frame.GetDocument()->GetSandboxFlags() == WebSandboxFlags::kNone; FeaturePolicy::FeatureState opener_feature_state = (not_sandboxed || propagate_sandbox) ? opener_frame.GetDocument()->GetFeaturePolicy()->GetFeatureState()
diff --git a/third_party/blink/renderer/core/page/pointer_lock_controller.cc b/third_party/blink/renderer/core/page/pointer_lock_controller.cc index e8a11d6b..cbc18b3 100644 --- a/third_party/blink/renderer/core/page/pointer_lock_controller.cc +++ b/third_party/blink/renderer/core/page/pointer_lock_controller.cc
@@ -53,7 +53,7 @@ WebFeature::kElementRequestPointerLockInShadow); } - if (target->GetDocument().IsSandboxed(kSandboxPointerLock)) { + if (target->GetDocument().IsSandboxed(WebSandboxFlags::kPointerLock)) { // FIXME: This message should be moved off the console once a solution to // https://bugs.webkit.org/show_bug.cgi?id=103274 exists. target->GetDocument().AddConsoleMessage(ConsoleMessage::Create(
diff --git a/third_party/blink/renderer/core/probe/core_probes.pidl b/third_party/blink/renderer/core/probe/core_probes.pidl index 18117db..5279eee 100644 --- a/third_party/blink/renderer/core/probe/core_probes.pidl +++ b/third_party/blink/renderer/core/probe/core_probes.pidl
@@ -94,7 +94,7 @@ void WillSendRequest(CoreProbeSink*, uint64_t identifier, DocumentLoader*, const KURL& fetch_context_url, const ResourceRequest&, const ResourceResponse& redirect_response, const FetchInitiatorInfo&, ResourceType); void WillSendNavigationRequest(CoreProbeSink*, uint64_t identifier, DocumentLoader*, const KURL&, const AtomicString& http_method, EncodedFormData*); void MarkResourceAsCached(LocalFrame*, DocumentLoader*, uint64_t identifier); - void DidReceiveResourceResponse(CoreProbeSink*, uint64_t identifier, DocumentLoader*, const ResourceResponse&, Resource*); + void DidReceiveResourceResponse(CoreProbeSink*, uint64_t identifier, DocumentLoader*, const ResourceResponse&, const Resource*); void DidReceiveData(CoreProbeSink*, uint64_t identifier, DocumentLoader*, const char* data, uint64_t data_length); void DidReceiveBlob(CoreProbeSink*, uint64_t identifier, DocumentLoader*, BlobDataHandle*); void DidReceiveEncodedDataLength(CoreProbeSink*, DocumentLoader* loader, uint64_t identifier, size_t encoded_data_length);
diff --git a/third_party/blink/renderer/core/svg/graphics/svg_image.cc b/third_party/blink/renderer/core/svg/graphics/svg_image.cc index 41c7d3f..aeb45d3 100644 --- a/third_party/blink/renderer/core/svg/graphics/svg_image.cc +++ b/third_party/blink/renderer/core/svg/graphics/svg_image.cc
@@ -795,7 +795,7 @@ } FrameLoader& loader = frame->Loader(); - loader.ForceSandboxFlags(kSandboxAll); + loader.ForceSandboxFlags(WebSandboxFlags::kAll); // SVG Images will always synthesize a viewBox, if it's not available, and // thus never see scrollbars.
diff --git a/third_party/blink/renderer/modules/BUILD.gn b/third_party/blink/renderer/modules/BUILD.gn index e894279..eb6f43aa 100644 --- a/third_party/blink/renderer/modules/BUILD.gn +++ b/third_party/blink/renderer/modules/BUILD.gn
@@ -323,6 +323,7 @@ "mediastream/media_stream_video_capturer_source_test.cc", "mediastream/mock_mojo_media_stream_dispatcher_host.cc", "mediastream/mock_mojo_media_stream_dispatcher_host.h", + "mediastream/video_track_adapter_unittest.cc", "notifications/notification_data_test.cc", "notifications/notification_image_loader_test.cc", "notifications/notification_resources_loader_test.cc",
diff --git a/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc b/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc index 7e274de..6692cff 100644 --- a/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc +++ b/third_party/blink/renderer/modules/cache_storage/global_cache_storage.cc
@@ -43,7 +43,7 @@ CacheStorage* Caches(T& fetching_scope, ExceptionState& exception_state) { ExecutionContext* context = fetching_scope.GetExecutionContext(); if (!context->GetSecurityOrigin()->CanAccessCacheStorage()) { - if (context->GetSecurityContext().IsSandboxed(kSandboxOrigin)) { + if (context->GetSecurityContext().IsSandboxed(WebSandboxFlags::kOrigin)) { exception_state.ThrowSecurityError( "Cache storage is disabled because the context is sandboxed and " "lacks the 'allow-same-origin' flag.");
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_promise.h b/third_party/blink/renderer/modules/clipboard/clipboard_promise.h index 1ee1ea4..0e37b458 100644 --- a/third_party/blink/renderer/modules/clipboard/clipboard_promise.h +++ b/third_party/blink/renderer/modules/clipboard/clipboard_promise.h
@@ -25,7 +25,7 @@ USING_GARBAGE_COLLECTED_MIXIN(ClipboardPromise); public: - ClipboardPromise(ScriptState*); + explicit ClipboardPromise(ScriptState*); virtual ~ClipboardPromise(); // Creates promise to execute Clipboard API functions off the main thread.
diff --git a/third_party/blink/renderer/modules/clipboard/clipboard_writer.h b/third_party/blink/renderer/modules/clipboard/clipboard_writer.h index 05e5a9b5..8c082a5 100644 --- a/third_party/blink/renderer/modules/clipboard/clipboard_writer.h +++ b/third_party/blink/renderer/modules/clipboard/clipboard_writer.h
@@ -39,7 +39,7 @@ void DidFail(FileErrorCode) override; protected: - ClipboardWriter(ClipboardPromise* promise); + explicit ClipboardWriter(ClipboardPromise* promise); virtual void DecodeOnBackgroundThread( scoped_refptr<base::SingleThreadTaskRunner> task_runner,
diff --git a/third_party/blink/renderer/modules/encryptedmedia/BUILD.gn b/third_party/blink/renderer/modules/encryptedmedia/BUILD.gn index 356f6d7..8aeb053 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/BUILD.gn +++ b/third_party/blink/renderer/modules/encryptedmedia/BUILD.gn
@@ -22,6 +22,8 @@ "media_key_status_map.h", "media_key_system_access.cc", "media_key_system_access.h", + "media_key_system_access_initializer_base.cc", + "media_key_system_access_initializer_base.h", "media_keys.cc", "media_keys.h", "media_keys_controller.cc",
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.cc b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.cc new file mode 100644 index 0000000..bc00ec6 --- /dev/null +++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.cc
@@ -0,0 +1,232 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.h" + +#include "services/metrics/public/cpp/ukm_builders.h" +#include "services/metrics/public/cpp/ukm_recorder.h" +#include "third_party/blink/renderer/core/dom/document.h" +#include "third_party/blink/renderer/core/inspector/console_message.h" +#include "third_party/blink/renderer/modules/encryptedmedia/encrypted_media_utils.h" +#include "third_party/blink/renderer/platform/histogram.h" +#include "third_party/blink/renderer/platform/network/parsed_content_type.h" +#include "third_party/blink/renderer/platform/wtf/wtf_size_t.h" + +namespace blink { + +namespace { + +static WebVector<WebEncryptedMediaInitDataType> ConvertInitDataTypes( + const Vector<String>& init_data_types) { + WebVector<WebEncryptedMediaInitDataType> result(init_data_types.size()); + for (wtf_size_t i = 0; i < init_data_types.size(); ++i) + result[i] = EncryptedMediaUtils::ConvertToInitDataType(init_data_types[i]); + return result; +} + +static WebMediaKeySystemMediaCapability::EncryptionScheme +ConvertEncryptionScheme(const String& encryption_scheme) { + if (encryption_scheme == "cenc") + return WebMediaKeySystemMediaCapability::EncryptionScheme::kCenc; + if (encryption_scheme == "cbcs") + return WebMediaKeySystemMediaCapability::EncryptionScheme::kCbcs; + + NOTREACHED(); + return WebMediaKeySystemMediaCapability::EncryptionScheme::kNotSpecified; +} + +static WebVector<WebMediaKeySystemMediaCapability> ConvertCapabilities( + const HeapVector<Member<MediaKeySystemMediaCapability>>& capabilities) { + WebVector<WebMediaKeySystemMediaCapability> result(capabilities.size()); + for (wtf_size_t i = 0; i < capabilities.size(); ++i) { + const WebString& content_type = capabilities[i]->contentType(); + result[i].content_type = content_type; + ParsedContentType type(content_type); + if (type.IsValid() && !type.GetParameters().HasDuplicatedNames()) { + // From + // http://w3c.github.io/encrypted-media/#get-supported-capabilities-for-audio-video-type + // "If the user agent does not recognize one or more parameters, + // continue to the next iteration." There is no way to enumerate the + // parameters, so only look up "codecs" if a single parameter is + // present. Chromium expects "codecs" to be provided, so this capability + // will be skipped if codecs is not the only parameter specified. + result[i].mime_type = type.MimeType(); + if (type.GetParameters().ParameterCount() == 1u) + result[i].codecs = type.ParameterValueForName("codecs"); + } + result[i].robustness = capabilities[i]->robustness(); + + // From + // https://github.com/WICG/encrypted-media-encryption-scheme/blob/master/explainer.md + // "Asking for "any" encryption scheme is unrealistic. Defining null as + // "any scheme" is convenient for backward compatibility, though. + // Applications which ignore this feature by leaving encryptionScheme null + // get the same user agent behavior they did before this feature existed." + result[i].encryption_scheme = + capabilities[i]->hasEncryptionScheme() + ? ConvertEncryptionScheme(capabilities[i]->encryptionScheme()) + : WebMediaKeySystemMediaCapability::EncryptionScheme::kNotSpecified; + } + return result; +} + +static WebVector<WebEncryptedMediaSessionType> ConvertSessionTypes( + const Vector<String>& session_types) { + WebVector<WebEncryptedMediaSessionType> result(session_types.size()); + for (wtf_size_t i = 0; i < session_types.size(); ++i) + result[i] = EncryptedMediaUtils::ConvertToSessionType(session_types[i]); + return result; +} + +} // namespace + +MediaKeySystemAccessInitializerBase::MediaKeySystemAccessInitializerBase( + ExecutionContext* execution_context, + const String& key_system, + const HeapVector<Member<MediaKeySystemConfiguration>>& + supported_configurations) + : ContextLifecycleObserver(execution_context), + key_system_(key_system), + supported_configurations_(supported_configurations.size()) { + for (wtf_size_t i = 0; i < supported_configurations.size(); ++i) { + const MediaKeySystemConfiguration* config = supported_configurations[i]; + WebMediaKeySystemConfiguration web_config; + + DCHECK(config->hasInitDataTypes()); + web_config.init_data_types = ConvertInitDataTypes(config->initDataTypes()); + + DCHECK(config->hasAudioCapabilities()); + web_config.audio_capabilities = + ConvertCapabilities(config->audioCapabilities()); + + DCHECK(config->hasVideoCapabilities()); + web_config.video_capabilities = + ConvertCapabilities(config->videoCapabilities()); + + DCHECK(config->hasDistinctiveIdentifier()); + web_config.distinctive_identifier = + EncryptedMediaUtils::ConvertToMediaKeysRequirement( + config->distinctiveIdentifier()); + + DCHECK(config->hasPersistentState()); + web_config.persistent_state = + EncryptedMediaUtils::ConvertToMediaKeysRequirement( + config->persistentState()); + + if (config->hasSessionTypes()) { + web_config.session_types = ConvertSessionTypes(config->sessionTypes()); + } else { + // From the spec + // (http://w3c.github.io/encrypted-media/#idl-def-mediakeysystemconfiguration): + // If this member is not present when the dictionary is passed to + // requestMediaKeySystemAccess(), the dictionary will be treated + // as if this member is set to [ "temporary" ]. + WebVector<WebEncryptedMediaSessionType> session_types( + static_cast<size_t>(1)); + session_types[0] = WebEncryptedMediaSessionType::kTemporary; + web_config.session_types = session_types; + } + + // If |label| is not present, it will be a null string. + web_config.label = config->label(); + supported_configurations_[i] = web_config; + } + + CheckVideoCapabilityRobustness(); +} + +const SecurityOrigin* MediaKeySystemAccessInitializerBase::GetSecurityOrigin() + const { + return IsExecutionContextValid() ? GetExecutionContext()->GetSecurityOrigin() + : nullptr; +} + +void MediaKeySystemAccessInitializerBase::Trace(blink::Visitor* visitor) { + EncryptedMediaRequest::Trace(visitor); + ContextLifecycleObserver::Trace(visitor); +} + +bool MediaKeySystemAccessInitializerBase::IsExecutionContextValid() const { + // isContextDestroyed() is called to see if the context is in the + // process of being destroyed. If it is true, assume the context is no + // longer valid as it is about to be destroyed anyway. + ExecutionContext* context = GetExecutionContext(); + return context && !context->IsContextDestroyed(); +} + +void MediaKeySystemAccessInitializerBase::CheckVideoCapabilityRobustness() + const { + const char kWidevineKeySystem[] = "com.widevine.alpha"; + const char kWidevineHwSecureAllRobustness[] = "HW_SECURE_ALL"; + + // Reported to UKM. Existing values must not change and new values must be + // added at the end of the list. + enum KeySystemForUkm { + kClearKey = 0, + kWidevine = 1, + }; + + // Only check for widevine key system for now. + if (KeySystem() != kWidevineKeySystem) + return; + + bool has_video_capabilities = false; + bool has_empty_robustness = false; + bool has_hw_secure_all = false; + + for (const auto& config : supported_configurations_) { + for (const auto& capability : config.video_capabilities) { + has_video_capabilities = true; + if (capability.robustness.IsEmpty()) { + has_empty_robustness = true; + } else if (capability.robustness == kWidevineHwSecureAllRobustness) { + has_hw_secure_all = true; + } + + if (has_empty_robustness && has_hw_secure_all) + break; + } + + if (has_empty_robustness && has_hw_secure_all) + break; + } + + if (has_video_capabilities) { + DEFINE_THREAD_SAFE_STATIC_LOCAL( + EnumerationHistogram, empty_robustness_histogram, + ("Media.EME.Widevine.VideoCapability.HasEmptyRobustness", 2)); + empty_robustness_histogram.Count(has_empty_robustness); + } + + if (has_empty_robustness) { + // TODO(xhwang): Write a best practice doc explaining details about risks of + // using an empty robustness here, and provide the link to the doc in this + // message. See http://crbug.com/720013 + GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( + mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kWarning, + "It is recommended that a robustness level be specified. Not " + "specifying the robustness level could result in unexpected " + "behavior.")); + } + + if (!IsExecutionContextValid()) + return; + + Document* document = To<Document>(GetExecutionContext()); + if (!document) + return; + + ukm::builders::Media_EME_RequestMediaKeySystemAccess builder( + document->UkmSourceID()); + builder.SetKeySystem(KeySystemForUkm::kWidevine); + builder.SetVideoCapabilities(static_cast<int>(has_video_capabilities)); + builder.SetVideoCapabilities_HasEmptyRobustness( + static_cast<int>(has_empty_robustness)); + builder.SetVideoCapabilities_HasHwSecureAllRobustness( + static_cast<int>(has_hw_secure_all)); + builder.Record(document->UkmRecorder()); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.h b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.h new file mode 100644 index 0000000..c1a2aaa --- /dev/null +++ b/third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.h
@@ -0,0 +1,58 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_ENCRYPTEDMEDIA_MEDIA_KEY_SYSTEM_ACCESS_INITIALIZER_BASE_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_ENCRYPTEDMEDIA_MEDIA_KEY_SYSTEM_ACCESS_INITIALIZER_BASE_H_ + +#include "third_party/blink/public/platform/web_media_key_system_configuration.h" +#include "third_party/blink/public/platform/web_vector.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" +#include "third_party/blink/renderer/core/execution_context/context_lifecycle_observer.h" +#include "third_party/blink/renderer/modules/encryptedmedia/media_key_system_configuration.h" +#include "third_party/blink/renderer/platform/encrypted_media_request.h" +#include "third_party/blink/renderer/platform/heap/member.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +class MediaKeySystemAccessInitializerBase : public EncryptedMediaRequest, + public ContextLifecycleObserver { + USING_GARBAGE_COLLECTED_MIXIN(MediaKeySystemAccessInitializerBase); + + public: + MediaKeySystemAccessInitializerBase( + ExecutionContext* execution_context, + const String& key_system, + const HeapVector<Member<MediaKeySystemConfiguration>>& + supported_configurations); + ~MediaKeySystemAccessInitializerBase() override = default; + + // EncryptedMediaRequest implementation. + WebString KeySystem() const override { return key_system_; } + const WebVector<WebMediaKeySystemConfiguration>& SupportedConfigurations() + const override { + return supported_configurations_; + } + const SecurityOrigin* GetSecurityOrigin() const override; + + void Trace(blink::Visitor* visitor) override; + + protected: + // Returns true if the ExecutionContext is valid, false otherwise. + bool IsExecutionContextValid() const; + + // For widevine key system, generate warning and report to UMA if + // |m_supportedConfigurations| contains any video capability with empty + // robustness string. + void CheckVideoCapabilityRobustness() const; + + const String key_system_; + WebVector<WebMediaKeySystemConfiguration> supported_configurations_; + + DISALLOW_COPY_AND_ASSIGN(MediaKeySystemAccessInitializerBase); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_ENCRYPTEDMEDIA_MEDIA_KEY_SYSTEM_ACCESS_INITIALIZER_BASE_H_
diff --git a/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc b/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc index ee5079d..ccb50dd 100644 --- a/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc +++ b/third_party/blink/renderer/modules/encryptedmedia/navigator_request_media_key_system_access.cc
@@ -8,8 +8,6 @@ #include "base/macros.h" #include "base/memory/ptr_util.h" -#include "services/metrics/public/cpp/ukm_builders.h" -#include "services/metrics/public/cpp/ukm_recorder.h" #include "third_party/blink/public/mojom/feature_policy/feature_policy.mojom-blink.h" #include "third_party/blink/public/platform/web_encrypted_media_client.h" #include "third_party/blink/public/platform/web_encrypted_media_request.h" @@ -27,11 +25,11 @@ #include "third_party/blink/renderer/modules/encryptedmedia/encrypted_media_utils.h" #include "third_party/blink/renderer/modules/encryptedmedia/media_key_session.h" #include "third_party/blink/renderer/modules/encryptedmedia/media_key_system_access.h" +#include "third_party/blink/renderer/modules/encryptedmedia/media_key_system_access_initializer_base.h" #include "third_party/blink/renderer/modules/encryptedmedia/media_keys_controller.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/v8_throw_exception.h" #include "third_party/blink/renderer/platform/encrypted_media_request.h" -#include "third_party/blink/renderer/platform/histogram.h" #include "third_party/blink/renderer/platform/network/mime/content_type.h" #include "third_party/blink/renderer/platform/network/parsed_content_type.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h" @@ -47,71 +45,10 @@ "applied to the current document. See https://goo.gl/EuHzyv for more " "details."; -static WebVector<WebEncryptedMediaInitDataType> ConvertInitDataTypes( - const Vector<String>& init_data_types) { - WebVector<WebEncryptedMediaInitDataType> result(init_data_types.size()); - for (wtf_size_t i = 0; i < init_data_types.size(); ++i) - result[i] = EncryptedMediaUtils::ConvertToInitDataType(init_data_types[i]); - return result; -} - -static WebMediaKeySystemMediaCapability::EncryptionScheme -ConvertEncryptionScheme(const String& encryption_scheme) { - if (encryption_scheme == "cenc") - return WebMediaKeySystemMediaCapability::EncryptionScheme::kCenc; - if (encryption_scheme == "cbcs") - return WebMediaKeySystemMediaCapability::EncryptionScheme::kCbcs; - - NOTREACHED(); - return WebMediaKeySystemMediaCapability::EncryptionScheme::kNotSpecified; -} - -static WebVector<WebMediaKeySystemMediaCapability> ConvertCapabilities( - const HeapVector<Member<MediaKeySystemMediaCapability>>& capabilities) { - WebVector<WebMediaKeySystemMediaCapability> result(capabilities.size()); - for (wtf_size_t i = 0; i < capabilities.size(); ++i) { - const WebString& content_type = capabilities[i]->contentType(); - result[i].content_type = content_type; - ParsedContentType type(content_type); - if (type.IsValid() && !type.GetParameters().HasDuplicatedNames()) { - // From - // http://w3c.github.io/encrypted-media/#get-supported-capabilities-for-audio-video-type - // "If the user agent does not recognize one or more parameters, - // continue to the next iteration." There is no way to enumerate the - // parameters, so only look up "codecs" if a single parameter is - // present. Chromium expects "codecs" to be provided, so this capability - // will be skipped if codecs is not the only parameter specified. - result[i].mime_type = type.MimeType(); - if (type.GetParameters().ParameterCount() == 1u) - result[i].codecs = type.ParameterValueForName("codecs"); - } - result[i].robustness = capabilities[i]->robustness(); - - // From - // https://github.com/WICG/encrypted-media-encryption-scheme/blob/master/explainer.md - // "Asking for "any" encryption scheme is unrealistic. Defining null as - // "any scheme" is convenient for backward compatibility, though. - // Applications which ignore this feature by leaving encryptionScheme null - // get the same user agent behavior they did before this feature existed." - result[i].encryption_scheme = - capabilities[i]->hasEncryptionScheme() - ? ConvertEncryptionScheme(capabilities[i]->encryptionScheme()) - : WebMediaKeySystemMediaCapability::EncryptionScheme::kNotSpecified; - } - return result; -} - -static WebVector<WebEncryptedMediaSessionType> ConvertSessionTypes( - const Vector<String>& session_types) { - WebVector<WebEncryptedMediaSessionType> result(session_types.size()); - for (wtf_size_t i = 0; i < session_types.size(); ++i) - result[i] = EncryptedMediaUtils::ConvertToSessionType(session_types[i]); - return result; -} - // This class allows capabilities to be checked and a MediaKeySystemAccess // object to be created asynchronously. -class MediaKeySystemAccessInitializer final : public EncryptedMediaRequest { +class MediaKeySystemAccessInitializer final + : public MediaKeySystemAccessInitializerBase { public: MediaKeySystemAccessInitializer( ScriptState*, @@ -121,12 +58,6 @@ ~MediaKeySystemAccessInitializer() override = default; // EncryptedMediaRequest implementation. - WebString KeySystem() const override { return key_system_; } - const WebVector<WebMediaKeySystemConfiguration>& SupportedConfigurations() - const override { - return supported_configurations_; - } - const SecurityOrigin* GetSecurityOrigin() const override; void RequestSucceeded( std::unique_ptr<WebContentDecryptionModuleAccess>) override; void RequestNotSupported(const WebString& error_message) override; @@ -135,22 +66,11 @@ void Trace(blink::Visitor* visitor) override { visitor->Trace(resolver_); - EncryptedMediaRequest::Trace(visitor); + MediaKeySystemAccessInitializerBase::Trace(visitor); } private: - // Returns true if the ExecutionContext is valid, false otherwise. - bool IsExecutionContextValid() const; - - // For widevine key system, generate warning and report to UMA if - // |m_supportedConfigurations| contains any video capability with empty - // robustness string. - void CheckVideoCapabilityRobustness() const; - Member<ScriptPromiseResolver> resolver_; - const String key_system_; - WebVector<WebMediaKeySystemConfiguration> supported_configurations_; - DISALLOW_COPY_AND_ASSIGN(MediaKeySystemAccessInitializer); }; @@ -159,62 +79,10 @@ const String& key_system, const HeapVector<Member<MediaKeySystemConfiguration>>& supported_configurations) - : resolver_(MakeGarbageCollected<ScriptPromiseResolver>(script_state)), - key_system_(key_system), - supported_configurations_(supported_configurations.size()) { - for (wtf_size_t i = 0; i < supported_configurations.size(); ++i) { - const MediaKeySystemConfiguration* config = supported_configurations[i]; - WebMediaKeySystemConfiguration web_config; - - DCHECK(config->hasInitDataTypes()); - web_config.init_data_types = ConvertInitDataTypes(config->initDataTypes()); - - DCHECK(config->hasAudioCapabilities()); - web_config.audio_capabilities = - ConvertCapabilities(config->audioCapabilities()); - - DCHECK(config->hasVideoCapabilities()); - web_config.video_capabilities = - ConvertCapabilities(config->videoCapabilities()); - - DCHECK(config->hasDistinctiveIdentifier()); - web_config.distinctive_identifier = - EncryptedMediaUtils::ConvertToMediaKeysRequirement( - config->distinctiveIdentifier()); - - DCHECK(config->hasPersistentState()); - web_config.persistent_state = - EncryptedMediaUtils::ConvertToMediaKeysRequirement( - config->persistentState()); - - if (config->hasSessionTypes()) { - web_config.session_types = ConvertSessionTypes(config->sessionTypes()); - } else { - // From the spec - // (http://w3c.github.io/encrypted-media/#idl-def-mediakeysystemconfiguration): - // If this member is not present when the dictionary is passed to - // requestMediaKeySystemAccess(), the dictionary will be treated - // as if this member is set to [ "temporary" ]. - WebVector<WebEncryptedMediaSessionType> session_types( - static_cast<size_t>(1)); - session_types[0] = WebEncryptedMediaSessionType::kTemporary; - web_config.session_types = session_types; - } - - // If |label| is not present, it will be a null string. - web_config.label = config->label(); - supported_configurations_[i] = web_config; - } - - CheckVideoCapabilityRobustness(); -} - -const SecurityOrigin* MediaKeySystemAccessInitializer::GetSecurityOrigin() - const { - return IsExecutionContextValid() - ? resolver_->GetExecutionContext()->GetSecurityOrigin() - : nullptr; -} + : MediaKeySystemAccessInitializerBase(ExecutionContext::From(script_state), + key_system, + supported_configurations), + resolver_(MakeGarbageCollected<ScriptPromiseResolver>(script_state)) {} void MediaKeySystemAccessInitializer::RequestSucceeded( std::unique_ptr<WebContentDecryptionModuleAccess> access) { @@ -240,84 +108,6 @@ resolver_.Clear(); } -bool MediaKeySystemAccessInitializer::IsExecutionContextValid() const { - // isContextDestroyed() is called to see if the context is in the - // process of being destroyed. If it is true, assume the context is no - // longer valid as it is about to be destroyed anyway. - ExecutionContext* context = resolver_->GetExecutionContext(); - return context && !context->IsContextDestroyed(); -} - -void MediaKeySystemAccessInitializer::CheckVideoCapabilityRobustness() const { - const char kWidevineKeySystem[] = "com.widevine.alpha"; - const char kWidevineHwSecureAllRobustness[] = "HW_SECURE_ALL"; - - // Reported to UKM. Existing values must not change and new values must be - // added at the end of the list. - enum KeySystemForUkm { - kClearKey = 0, - kWidevine = 1, - }; - - // Only check for widevine key system for now. - if (KeySystem() != kWidevineKeySystem) - return; - - bool has_video_capabilities = false; - bool has_empty_robustness = false; - bool has_hw_secure_all = false; - - for (const auto& config : supported_configurations_) { - for (const auto& capability : config.video_capabilities) { - has_video_capabilities = true; - if (capability.robustness.IsEmpty()) { - has_empty_robustness = true; - } else if (capability.robustness == kWidevineHwSecureAllRobustness) { - has_hw_secure_all = true; - } - - if (has_empty_robustness && has_hw_secure_all) - break; - } - - if (has_empty_robustness && has_hw_secure_all) - break; - } - - if (has_video_capabilities) { - DEFINE_THREAD_SAFE_STATIC_LOCAL( - EnumerationHistogram, empty_robustness_histogram, - ("Media.EME.Widevine.VideoCapability.HasEmptyRobustness", 2)); - empty_robustness_histogram.Count(has_empty_robustness); - } - - if (has_empty_robustness) { - // TODO(xhwang): Write a best practice doc explaining details about risks of - // using an empty robustness here, and provide the link to the doc in this - // message. See http://crbug.com/720013 - resolver_->GetExecutionContext()->AddConsoleMessage(ConsoleMessage::Create( - mojom::ConsoleMessageSource::kJavaScript, - mojom::ConsoleMessageLevel::kWarning, - "It is recommended that a robustness level be specified. Not " - "specifying the robustness level could result in unexpected " - "behavior.")); - } - - Document* document = To<Document>(resolver_->GetExecutionContext()); - if (!document) - return; - - ukm::builders::Media_EME_RequestMediaKeySystemAccess builder( - document->UkmSourceID()); - builder.SetKeySystem(KeySystemForUkm::kWidevine); - builder.SetVideoCapabilities(static_cast<int>(has_video_capabilities)); - builder.SetVideoCapabilities_HasEmptyRobustness( - static_cast<int>(has_empty_robustness)); - builder.SetVideoCapabilities_HasHwSecureAllRobustness( - static_cast<int>(has_hw_secure_all)); - builder.Record(document->UkmRecorder()); -} - } // namespace ScriptPromise NavigatorRequestMediaKeySystemAccess::requestMediaKeySystemAccess(
diff --git a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc index 2fcbd13c..0839428 100644 --- a/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc +++ b/third_party/blink/renderer/modules/exported/web_embedded_worker_impl.cc
@@ -376,8 +376,8 @@ const HttpsState starter_https_state = document->GetHttpsState(); auto* worker_clients = MakeGarbageCollected<WorkerClients>(); - ProvideIndexedDBClientToWorker(worker_clients, - IndexedDBClient::Create(*worker_clients)); + ProvideIndexedDBClientToWorker( + worker_clients, MakeGarbageCollected<IndexedDBClient>(*worker_clients)); ProvideContentSettingsClientToWorker(worker_clients, std::move(content_settings_client_));
diff --git a/third_party/blink/renderer/modules/imagecapture/image_capture.cc b/third_party/blink/renderer/modules/imagecapture/image_capture.cc index bf755d1..122e66ff 100644 --- a/third_party/blink/renderer/modules/imagecapture/image_capture.cc +++ b/third_party/blink/renderer/modules/imagecapture/image_capture.cc
@@ -700,7 +700,7 @@ photo_settings_->setImageWidth(photo_state->width->current); // TODO(mcasas): collect the remaining two entries https://crbug.com/732521. - photo_capabilities_ = PhotoCapabilities::Create(); + photo_capabilities_ = MakeGarbageCollected<PhotoCapabilities>(); photo_capabilities_->SetRedEyeReduction(photo_state->red_eye_reduction); // TODO(mcasas): Remove the explicit MediaSettingsRange::create() when // mojo::StructTraits supports garbage-collected mappings,
diff --git a/third_party/blink/renderer/modules/imagecapture/photo_capabilities.cc b/third_party/blink/renderer/modules/imagecapture/photo_capabilities.cc index 7da6e62..4c2beb9 100644 --- a/third_party/blink/renderer/modules/imagecapture/photo_capabilities.cc +++ b/third_party/blink/renderer/modules/imagecapture/photo_capabilities.cc
@@ -6,11 +6,6 @@ namespace blink { -// static -PhotoCapabilities* PhotoCapabilities::Create() { - return MakeGarbageCollected<PhotoCapabilities>(); -} - Vector<String> PhotoCapabilities::fillLightMode() const { Vector<String> fill_light_modes; for (const auto& mode : fill_light_modes_) {
diff --git a/third_party/blink/renderer/modules/imagecapture/photo_capabilities.h b/third_party/blink/renderer/modules/imagecapture/photo_capabilities.h index 802b653..f1c0095d 100644 --- a/third_party/blink/renderer/modules/imagecapture/photo_capabilities.h +++ b/third_party/blink/renderer/modules/imagecapture/photo_capabilities.h
@@ -17,8 +17,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static PhotoCapabilities* Create(); - PhotoCapabilities() = default; ~PhotoCapabilities() override = default;
diff --git a/third_party/blink/renderer/modules/indexeddb/global_indexed_db.cc b/third_party/blink/renderer/modules/indexeddb/global_indexed_db.cc index ea3e68c..2bfd373 100644 --- a/third_party/blink/renderer/modules/indexeddb/global_indexed_db.cc +++ b/third_party/blink/renderer/modules/indexeddb/global_indexed_db.cc
@@ -37,7 +37,7 @@ IDBFactory* IdbFactory(T& fetching_scope) { if (!idb_factory_) - idb_factory_ = IDBFactory::Create(); + idb_factory_ = MakeGarbageCollected<IDBFactory>(); return idb_factory_; }
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc b/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc index 7e97b25..c63514a 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_cursor.cc
@@ -43,15 +43,6 @@ namespace blink { -IDBCursor* IDBCursor::Create(std::unique_ptr<WebIDBCursor> backend, - mojom::IDBCursorDirection direction, - IDBRequest* request, - const Source& source, - IDBTransaction* transaction) { - return MakeGarbageCollected<IDBCursor>(std::move(backend), direction, request, - source, transaction); -} - IDBCursor::IDBCursor(std::unique_ptr<WebIDBCursor> backend, mojom::IDBCursorDirection direction, IDBRequest* request,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_cursor.h b/third_party/blink/renderer/modules/indexeddb/idb_cursor.h index f5a1ba8..6df0b0a9 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_cursor.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_cursor.h
@@ -52,12 +52,6 @@ static mojom::IDBCursorDirection StringToDirection(const String& mode_string); - static IDBCursor* Create(std::unique_ptr<WebIDBCursor>, - mojom::IDBCursorDirection, - IDBRequest*, - const Source&, - IDBTransaction*); - IDBCursor(std::unique_ptr<WebIDBCursor>, mojom::IDBCursorDirection, IDBRequest*,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.cc b/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.cc index 7df7371..101e265f 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.cc
@@ -30,16 +30,6 @@ namespace blink { -IDBCursorWithValue* IDBCursorWithValue::Create( - std::unique_ptr<WebIDBCursor> backend, - mojom::IDBCursorDirection direction, - IDBRequest* request, - const Source& source, - IDBTransaction* transaction) { - return MakeGarbageCollected<IDBCursorWithValue>(std::move(backend), direction, - request, source, transaction); -} - IDBCursorWithValue::IDBCursorWithValue(std::unique_ptr<WebIDBCursor> backend, mojom::IDBCursorDirection direction, IDBRequest* request,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h b/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h index 4c0deb78..559640e 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_cursor_with_value.h
@@ -41,12 +41,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static IDBCursorWithValue* Create(std::unique_ptr<WebIDBCursor>, - mojom::IDBCursorDirection, - IDBRequest*, - const Source&, - IDBTransaction*); - IDBCursorWithValue(std::unique_ptr<WebIDBCursor>, mojom::IDBCursorDirection, IDBRequest*,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_database.cc b/third_party/blink/renderer/modules/indexeddb/idb_database.cc index cc2f5293..3fad0b87 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_database.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_database.cc
@@ -92,14 +92,6 @@ const char IDBDatabase::kDatabaseClosedErrorMessage[] = "The database connection is closed."; -IDBDatabase* IDBDatabase::Create(ExecutionContext* context, - std::unique_ptr<WebIDBDatabase> database, - IDBDatabaseCallbacks* callbacks, - v8::Isolate* isolate) { - return MakeGarbageCollected<IDBDatabase>(context, std::move(database), - callbacks, isolate); -} - IDBDatabase::IDBDatabase(ExecutionContext* context, std::unique_ptr<WebIDBDatabase> backend, IDBDatabaseCallbacks* callbacks, @@ -210,8 +202,8 @@ } observer->Callback()->InvokeAndReportException( - observer, IDBObserverChanges::Create(this, nullptr, observations, - map_entry.second)); + observer, MakeGarbageCollected<IDBObserverChanges>( + this, nullptr, observations, map_entry.second)); } } } @@ -308,8 +300,8 @@ base::AdoptRef(new IDBObjectStoreMetadata( name, object_store_id, key_path, auto_increment, WebIDBDatabase::kMinimumIndexId)); - IDBObjectStore* object_store = - IDBObjectStore::Create(store_metadata, version_change_transaction_.Get()); + auto* object_store = MakeGarbageCollected<IDBObjectStore>( + store_metadata, version_change_transaction_.Get()); version_change_transaction_->ObjectStoreCreated(name, object_store); metadata_.object_stores.Set(object_store_id, std::move(store_metadata)); ++metadata_.max_object_store_id;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_database.h b/third_party/blink/renderer/modules/indexeddb/idb_database.h index 6e86526..2020565 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_database.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_database.h
@@ -63,11 +63,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static IDBDatabase* Create(ExecutionContext*, - std::unique_ptr<WebIDBDatabase>, - IDBDatabaseCallbacks*, - v8::Isolate*); - IDBDatabase(ExecutionContext*, std::unique_ptr<WebIDBDatabase>, IDBDatabaseCallbacks*,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.cc b/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.cc index 88d4cb7..cf324f4f 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.cc
@@ -30,10 +30,6 @@ namespace blink { -IDBDatabaseCallbacks* IDBDatabaseCallbacks::Create() { - return MakeGarbageCollected<IDBDatabaseCallbacks>(); -} - IDBDatabaseCallbacks::IDBDatabaseCallbacks() : database_(nullptr) {} IDBDatabaseCallbacks::~IDBDatabaseCallbacks() = default;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.h b/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.h index 1da199a..13a020c 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_database_callbacks.h
@@ -41,8 +41,6 @@ class MODULES_EXPORT IDBDatabaseCallbacks : public GarbageCollectedFinalized<IDBDatabaseCallbacks> { public: - static IDBDatabaseCallbacks* Create(); - IDBDatabaseCallbacks(); virtual ~IDBDatabaseCallbacks(); void Trace(blink::Visitor*);
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc index f352f44..1e35a4b 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_factory.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_factory.cc
@@ -316,7 +316,7 @@ WebFeature::kFileAccessedDatabase); } - IDBDatabaseCallbacks* database_callbacks = IDBDatabaseCallbacks::Create(); + auto* database_callbacks = MakeGarbageCollected<IDBDatabaseCallbacks>(); int64_t transaction_id = IDBDatabase::NextTransactionId(); auto transaction_backend = std::make_unique<WebIDBTransactionImpl>( @@ -325,7 +325,7 @@ transaction_id); mojom::blink::IDBTransactionAssociatedRequest transaction_request = transaction_backend->CreateRequest(); - IDBOpenDBRequest* request = IDBOpenDBRequest::Create( + auto* request = MakeGarbageCollected<IDBOpenDBRequest>( script_state, database_callbacks, std::move(transaction_backend), transaction_id, version, std::move(metrics)); @@ -393,7 +393,7 @@ WebFeature::kFileAccessedDatabase); } - IDBOpenDBRequest* request = IDBOpenDBRequest::Create( + auto* request = MakeGarbageCollected<IDBOpenDBRequest>( script_state, nullptr, /*IDBTransactionAssociatedPtr=*/nullptr, 0, IDBDatabaseMetadata::kDefaultVersion, std::move(metrics));
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory.h b/third_party/blink/renderer/modules/indexeddb/idb_factory.h index 825ff1d6..461aa05 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_factory.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_factory.h
@@ -46,12 +46,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static IDBFactory* Create() { return MakeGarbageCollected<IDBFactory>(); } - static IDBFactory* CreateForTest( - std::unique_ptr<WebIDBFactory> web_idb_factory) { - return MakeGarbageCollected<IDBFactory>(std::move(web_idb_factory)); - } - IDBFactory(); IDBFactory(std::unique_ptr<WebIDBFactory>);
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc b/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc index c50291e8..bbe65a2 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_factory_test.cc
@@ -61,7 +61,7 @@ auto web_factory = std::make_unique<MockWebIDBFactory>(); std::unique_ptr<WebIDBCallbacks> callbacks; web_factory->SetCallbacksPointer(&callbacks); - IDBFactory* factory = IDBFactory::CreateForTest(std::move(web_factory)); + auto* factory = MakeGarbageCollected<IDBFactory>(std::move(web_factory)); DummyExceptionStateForTesting exception_state; ScriptPromise promise = @@ -94,7 +94,7 @@ auto web_factory = std::make_unique<MockWebIDBFactory>(); std::unique_ptr<WebIDBCallbacks> callbacks; web_factory->SetCallbacksPointer(&callbacks); - IDBFactory* factory = IDBFactory::CreateForTest(std::move(web_factory)); + auto* factory = MakeGarbageCollected<IDBFactory>(std::move(web_factory)); DummyExceptionStateForTesting exception_state; ScriptPromise promise =
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_index.h b/third_party/blink/renderer/modules/indexeddb/idb_index.h index 751a75b8..221839a1 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_index.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_index.h
@@ -48,13 +48,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static IDBIndex* Create(scoped_refptr<IDBIndexMetadata> metadata, - IDBObjectStore* object_store, - IDBTransaction* transaction) { - return MakeGarbageCollected<IDBIndex>(std::move(metadata), object_store, - transaction); - } - IDBIndex(scoped_refptr<IDBIndexMetadata>, IDBObjectStore*, IDBTransaction*); ~IDBIndex() override;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc index d1175be..3e04775 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.cc
@@ -694,17 +694,6 @@ // cursor success handlers are kept alive. class IndexPopulator final : public NativeEventListener { public: - static IndexPopulator* Create( - ScriptState* script_state, - IDBDatabase* database, - int64_t transaction_id, - int64_t object_store_id, - scoped_refptr<const IDBIndexMetadata> index_metadata) { - return MakeGarbageCollected<IndexPopulator>(script_state, database, - transaction_id, object_store_id, - std::move(index_metadata)); - } - IndexPopulator(ScriptState* script_state, IDBDatabase* database, int64_t transaction_id, @@ -843,7 +832,8 @@ scoped_refptr<IDBIndexMetadata> index_metadata = base::AdoptRef(new IDBIndexMetadata( name, index_id, key_path, options->unique(), options->multiEntry())); - IDBIndex* index = IDBIndex::Create(index_metadata, this, transaction_.Get()); + auto* index = + MakeGarbageCollected<IDBIndex>(index_metadata, this, transaction_.Get()); index_map_.Set(name, index); metadata_->indexes.Set(index_id, index_metadata); @@ -858,7 +848,7 @@ // This is kept alive by being the success handler of the request, which is in // turn kept alive by the owning transaction. - IndexPopulator* index_populator = IndexPopulator::Create( + auto* index_populator = MakeGarbageCollected<IndexPopulator>( script_state, transaction()->db(), transaction_->Id(), Id(), std::move(index_metadata)); index_request->setOnsuccess(index_populator); @@ -896,8 +886,8 @@ scoped_refptr<IDBIndexMetadata> index_metadata = Metadata().indexes.at(index_id); DCHECK(index_metadata.get()); - IDBIndex* index = - IDBIndex::Create(std::move(index_metadata), this, transaction_.Get()); + auto* index = MakeGarbageCollected<IDBIndex>(std::move(index_metadata), this, + transaction_.Get()); index_map_.Set(name, index); return index; }
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_object_store.h b/third_party/blink/renderer/modules/indexeddb/idb_object_store.h index a91472d4..8581ce9 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_object_store.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_object_store.h
@@ -51,12 +51,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static IDBObjectStore* Create(scoped_refptr<IDBObjectStoreMetadata> metadata, - IDBTransaction* transaction) { - return MakeGarbageCollected<IDBObjectStore>(std::move(metadata), - transaction); - } - IDBObjectStore(scoped_refptr<IDBObjectStoreMetadata>, IDBTransaction*); ~IDBObjectStore() override = default;
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_observation.cc b/third_party/blink/renderer/modules/indexeddb/idb_observation.cc index 6abddba..030bc57 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_observation.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_observation.cc
@@ -65,14 +65,6 @@ } } -IDBObservation* IDBObservation::Create(int64_t object_store_id, - mojom::IDBOperationType type, - IDBKeyRange* key_range, - std::unique_ptr<IDBValue> value) { - return MakeGarbageCollected<IDBObservation>(object_store_id, type, key_range, - std::move(value)); -} - IDBObservation::IDBObservation(int64_t object_store_id, mojom::IDBOperationType type, IDBKeyRange* key_range,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_observation.h b/third_party/blink/renderer/modules/indexeddb/idb_observation.h index 8964fd9e..831fae9 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_observation.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_observation.h
@@ -25,11 +25,6 @@ public: static mojom::IDBOperationType StringToOperationType(const String&); - static IDBObservation* Create(int64_t object_store_id, - mojom::IDBOperationType type, - IDBKeyRange* key_range, - std::unique_ptr<IDBValue> value); - IDBObservation(int64_t object_store_id, mojom::IDBOperationType type, IDBKeyRange* key_range,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.cc b/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.cc index cbf4b733..f8b1e48 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.cc
@@ -28,15 +28,6 @@ return ScriptValue::From(script_state, map); } -IDBObserverChanges* IDBObserverChanges::Create( - IDBDatabase* database, - IDBTransaction* transaction, - const Vector<Persistent<IDBObservation>>& observations, - const Vector<int32_t>& observation_indices) { - return MakeGarbageCollected<IDBObserverChanges>( - database, transaction, observations, observation_indices); -} - IDBObserverChanges::IDBObserverChanges( IDBDatabase* database, IDBTransaction* transaction,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.h b/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.h index aa7a3a0..874589d 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_observer_changes.h
@@ -20,12 +20,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static IDBObserverChanges* Create( - IDBDatabase*, - IDBTransaction*, - const Vector<Persistent<IDBObservation>>& observations, - const Vector<int32_t>& observation_indices); - IDBObserverChanges(IDBDatabase*, IDBTransaction*, const Vector<Persistent<IDBObservation>>& observations,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc b/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc index c71ac004..5b2d5db3 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.cc
@@ -38,18 +38,6 @@ namespace blink { -IDBOpenDBRequest* IDBOpenDBRequest::Create( - ScriptState* script_state, - IDBDatabaseCallbacks* callbacks, - std::unique_ptr<WebIDBTransaction> transaction_backend, - int64_t transaction_id, - int64_t version, - IDBRequest::AsyncTraceState metrics) { - return MakeGarbageCollected<IDBOpenDBRequest>( - script_state, callbacks, std::move(transaction_backend), transaction_id, - version, std::move(metrics)); -} - IDBOpenDBRequest::IDBOpenDBRequest( ScriptState* script_state, IDBDatabaseCallbacks* callbacks, @@ -111,9 +99,9 @@ DCHECK(database_callbacks_); - IDBDatabase* idb_database = - IDBDatabase::Create(GetExecutionContext(), std::move(backend), - database_callbacks_.Release(), isolate_); + auto* idb_database = MakeGarbageCollected<IDBDatabase>( + GetExecutionContext(), std::move(backend), database_callbacks_.Release(), + isolate_); idb_database->SetMetadata(metadata); if (old_version == IDBDatabaseMetadata::kNoVersion) { @@ -153,9 +141,9 @@ } else { DCHECK(backend.get()); DCHECK(database_callbacks_); - idb_database = - IDBDatabase::Create(GetExecutionContext(), std::move(backend), - database_callbacks_.Release(), isolate_); + idb_database = MakeGarbageCollected<IDBDatabase>( + GetExecutionContext(), std::move(backend), + database_callbacks_.Release(), isolate_); SetResult(IDBAny::Create(idb_database)); } idb_database->SetMetadata(metadata);
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h b/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h index 2db74510..57fa3f5 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h +++ b/third_party/blink/renderer/modules/indexeddb/idb_open_db_request.h
@@ -39,14 +39,6 @@ DEFINE_WRAPPERTYPEINFO(); public: - static IDBOpenDBRequest* Create( - ScriptState*, - IDBDatabaseCallbacks*, - std::unique_ptr<WebIDBTransaction> transaction_backend, - int64_t transaction_id, - int64_t version, - IDBRequest::AsyncTraceState metrics); - IDBOpenDBRequest(ScriptState*, IDBDatabaseCallbacks*, std::unique_ptr<WebIDBTransaction> transaction_backend,
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request.cc b/third_party/blink/renderer/modules/indexeddb/idb_request.cc index bb5fdaa7..7ca6c4f 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_request.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_request.cc
@@ -458,12 +458,14 @@ switch (cursor_type_) { case indexed_db::kCursorKeyOnly: - cursor = IDBCursor::Create(std::move(backend), cursor_direction_, this, - source, transaction_.Get()); + cursor = + MakeGarbageCollected<IDBCursor>(std::move(backend), cursor_direction_, + this, source, transaction_.Get()); break; case indexed_db::kCursorKeyAndValue: - cursor = IDBCursorWithValue::Create(std::move(backend), cursor_direction_, - this, source, transaction_.Get()); + cursor = MakeGarbageCollected<IDBCursorWithValue>( + std::move(backend), cursor_direction_, this, source, + transaction_.Get()); break; default: NOTREACHED();
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc b/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc index f3e048a9..454fde5 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_request_test.cc
@@ -181,9 +181,9 @@ V8TestingScope& scope, std::unique_ptr<MockWebIDBDatabase> database_backend, std::unique_ptr<MockWebIDBTransaction> transaction_backend) { - db_ = IDBDatabase::Create( + db_ = MakeGarbageCollected<IDBDatabase>( scope.GetExecutionContext(), std::move(database_backend), - IDBDatabaseCallbacks::Create(), scope.GetIsolate()); + MakeGarbageCollected<IDBDatabaseCallbacks>(), scope.GetIsolate()); HashSet<String> transaction_scope = {"store"}; transaction_ = IDBTransaction::CreateNonVersionChange( @@ -193,7 +193,7 @@ IDBKeyPath store_key_path("primaryKey"); scoped_refptr<IDBObjectStoreMetadata> store_metadata = base::AdoptRef( new IDBObjectStoreMetadata("store", kStoreId, store_key_path, true, 1)); - store_ = IDBObjectStore::Create(store_metadata, transaction_); + store_ = MakeGarbageCollected<IDBObjectStore>(store_metadata, transaction_); } WebURLLoaderMockFactory* url_loader_mock_factory_; @@ -374,7 +374,8 @@ const int64_t kVersion = 1; const int64_t kOldVersion = 0; const IDBDatabaseMetadata metadata; - Persistent<IDBDatabaseCallbacks> callbacks = IDBDatabaseCallbacks::Create(); + Persistent<IDBDatabaseCallbacks> callbacks = + MakeGarbageCollected<IDBDatabaseCallbacks>(); { mojom::blink::IDBDatabaseAssociatedPtr ptr; @@ -386,7 +387,7 @@ auto transaction_backend = std::make_unique<MockWebIDBTransaction>( scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess), kTransactionId); - IDBOpenDBRequest* request = IDBOpenDBRequest::Create( + auto* request = MakeGarbageCollected<IDBOpenDBRequest>( scope.GetScriptState(), callbacks, std::move(transaction_backend), kTransactionId, kVersion, IDBRequest::AsyncTraceState()); EXPECT_EQ(request->readyState(), "pending"); @@ -408,7 +409,7 @@ auto transaction_backend = std::make_unique<MockWebIDBTransaction>( scope.GetExecutionContext()->GetTaskRunner(TaskType::kDatabaseAccess), kTransactionId); - IDBOpenDBRequest* request = IDBOpenDBRequest::Create( + auto* request = MakeGarbageCollected<IDBOpenDBRequest>( scope.GetScriptState(), callbacks, std::move(transaction_backend), kTransactionId, kVersion, IDBRequest::AsyncTraceState()); EXPECT_EQ(request->readyState(), "pending");
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc b/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc index 97dadd3..a16a2be 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_transaction.cc
@@ -193,8 +193,8 @@ database_->Metadata().object_stores.at(object_store_id); DCHECK(object_store_metadata.get()); - IDBObjectStore* object_store = - IDBObjectStore::Create(std::move(object_store_metadata), this); + auto* object_store = MakeGarbageCollected<IDBObjectStore>( + std::move(object_store_metadata), this); DCHECK(!object_store_map_.Contains(name)); object_store_map_.Set(name, object_store);
diff --git a/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc b/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc index b6cd7dd2..cc1a1f3 100644 --- a/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc +++ b/third_party/blink/renderer/modules/indexeddb/idb_transaction_test.cc
@@ -64,9 +64,6 @@ class FakeIDBDatabaseCallbacks final : public IDBDatabaseCallbacks { public: - static FakeIDBDatabaseCallbacks* Create() { - return MakeGarbageCollected<FakeIDBDatabaseCallbacks>(); - } FakeIDBDatabaseCallbacks() = default; void OnVersionChange(int64_t old_version, int64_t new_version) override {} void OnForcedClose() override {} @@ -92,9 +89,9 @@ V8TestingScope& scope, std::unique_ptr<MockWebIDBDatabase> database_backend, std::unique_ptr<MockWebIDBTransaction> transaction_backend) { - db_ = IDBDatabase::Create( + db_ = MakeGarbageCollected<IDBDatabase>( scope.GetExecutionContext(), std::move(database_backend), - FakeIDBDatabaseCallbacks::Create(), scope.GetIsolate()); + MakeGarbageCollected<FakeIDBDatabaseCallbacks>(), scope.GetIsolate()); HashSet<String> transaction_scope = {"store"}; transaction_ = IDBTransaction::CreateNonVersionChange( @@ -104,7 +101,7 @@ IDBKeyPath store_key_path("primaryKey"); scoped_refptr<IDBObjectStoreMetadata> store_metadata = base::AdoptRef( new IDBObjectStoreMetadata("store", kStoreId, store_key_path, true, 1)); - store_ = IDBObjectStore::Create(store_metadata, transaction_); + store_ = MakeGarbageCollected<IDBObjectStore>(store_metadata, transaction_); } WebURLLoaderMockFactory* url_loader_mock_factory_;
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_client.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_client.cc index f2f3785..723c11b 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_client.cc +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_client.cc
@@ -17,14 +17,6 @@ namespace blink { -IndexedDBClient* IndexedDBClient::Create(LocalFrame& frame) { - return MakeGarbageCollected<IndexedDBClient>(frame); -} - -IndexedDBClient* IndexedDBClient::Create(WorkerClients& worker_clients) { - return MakeGarbageCollected<IndexedDBClient>(worker_clients); -} - IndexedDBClient::IndexedDBClient(LocalFrame& frame) : Supplement<LocalFrame>(frame) {}
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_client.h b/third_party/blink/renderer/modules/indexeddb/indexed_db_client.h index 948d42d..77e52b5 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_client.h +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_client.h
@@ -52,9 +52,6 @@ public: static const char kSupplementName[]; - static IndexedDBClient* Create(LocalFrame&); - static IndexedDBClient* Create(WorkerClients&); - explicit IndexedDBClient(LocalFrame&); explicit IndexedDBClient(WorkerClients&);
diff --git a/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc b/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc index 22aa44a..c92e2f13 100644 --- a/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc +++ b/third_party/blink/renderer/modules/indexeddb/indexed_db_database_callbacks_impl.cc
@@ -53,9 +53,9 @@ value = std::make_unique<IDBValue>(scoped_refptr<SharedBuffer>(), Vector<WebBlobInfo>()); } - observations.emplace_back( - IDBObservation::Create(observation->object_store_id, observation->type, - key_range, std::move(value))); + observations.emplace_back(MakeGarbageCollected<IDBObservation>( + observation->object_store_id, observation->type, key_range, + std::move(value))); } std::unordered_map<int32_t, Vector<int32_t>> observation_index_map;
diff --git a/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc b/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc index d0d970f..3c4bf94 100644 --- a/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc +++ b/third_party/blink/renderer/modules/indexeddb/inspector_indexed_db_agent.cc
@@ -111,13 +111,6 @@ class GetDatabaseNamesCallback final : public NativeEventListener { public: - static GetDatabaseNamesCallback* Create( - std::unique_ptr<RequestDatabaseNamesCallback> request_callback, - const String& security_origin) { - return MakeGarbageCollected<GetDatabaseNamesCallback>( - std::move(request_callback), security_origin); - } - GetDatabaseNamesCallback( std::unique_ptr<RequestDatabaseNamesCallback> request_callback, const String& security_origin) @@ -154,13 +147,6 @@ class DeleteCallback final : public NativeEventListener { public: - static DeleteCallback* Create( - std::unique_ptr<DeleteDatabaseCallback> request_callback, - const String& security_origin) { - return MakeGarbageCollected<DeleteCallback>(std::move(request_callback), - security_origin); - } - DeleteCallback(std::unique_ptr<DeleteDatabaseCallback> request_callback, const String& security_origin) : request_callback_(std::move(request_callback)), @@ -787,7 +773,7 @@ } idb_request->addEventListener( event_type_names::kSuccess, - GetDatabaseNamesCallback::Create( + MakeGarbageCollected<GetDatabaseNamesCallback>( std::move(request_callback), document->GetSecurityOrigin()->ToRawString()), false); @@ -970,12 +956,6 @@ class DeleteObjectStoreEntriesListener final : public NativeEventListener { public: - static DeleteObjectStoreEntriesListener* Create( - std::unique_ptr<DeleteObjectStoreEntriesCallback> request_callback) { - return MakeGarbageCollected<DeleteObjectStoreEntriesListener>( - std::move(request_callback)); - } - DeleteObjectStoreEntriesListener( std::unique_ptr<DeleteObjectStoreEntriesCallback> request_callback) : request_callback_(std::move(request_callback)) {} @@ -1035,7 +1015,8 @@ idb_object_store->deleteFunction(script_state, idb_key_range_.Get()); idb_request->addEventListener( event_type_names::kSuccess, - DeleteObjectStoreEntriesListener::Create(std::move(request_callback_)), + MakeGarbageCollected<DeleteObjectStoreEntriesListener>( + std::move(request_callback_)), false); } @@ -1070,12 +1051,6 @@ class ClearObjectStoreListener final : public NativeEventListener { public: - static ClearObjectStoreListener* Create( - std::unique_ptr<ClearObjectStoreCallback> request_callback) { - return MakeGarbageCollected<ClearObjectStoreListener>( - std::move(request_callback)); - } - ClearObjectStoreListener( std::unique_ptr<ClearObjectStoreCallback> request_callback) : request_callback_(std::move(request_callback)) {} @@ -1138,7 +1113,9 @@ } idb_transaction->addEventListener( event_type_names::kComplete, - ClearObjectStoreListener::Create(std::move(request_callback_)), false); + MakeGarbageCollected<ClearObjectStoreListener>( + std::move(request_callback_)), + false); } ClearObjectStoreCallback* GetRequestCallback() override { @@ -1196,8 +1173,9 @@ } idb_request->addEventListener( event_type_names::kSuccess, - DeleteCallback::Create(std::move(request_callback), - document->GetSecurityOrigin()->ToRawString()), + MakeGarbageCollected<DeleteCallback>( + std::move(request_callback), + document->GetSecurityOrigin()->ToRawString()), false); }
diff --git a/third_party/blink/renderer/modules/mediastream/BUILD.gn b/third_party/blink/renderer/modules/mediastream/BUILD.gn index 3ee2db8..dbfe955 100644 --- a/third_party/blink/renderer/modules/mediastream/BUILD.gn +++ b/third_party/blink/renderer/modules/mediastream/BUILD.gn
@@ -48,6 +48,7 @@ "user_media_request.cc", "user_media_request.h", "video_track_adapter.cc", + "video_track_adapter.h", "video_track_adapter_settings.cc", "web_media_stream_utils.cc", ]
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc index e0a5467f..ac1efc2 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_source.cc
@@ -20,7 +20,7 @@ #include "third_party/blink/public/platform/platform.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_constraints_util_video_device.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h" -#include "third_party/blink/public/web/modules/mediastream/video_track_adapter.h" +#include "third_party/blink/renderer/modules/mediastream/video_track_adapter.h" namespace blink {
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc index 83f8f2cb..a45f52f 100644 --- a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc +++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter.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/blink/public/web/modules/mediastream/video_track_adapter.h" +#include "third_party/blink/renderer/modules/mediastream/video_track_adapter.h" #include <algorithm> #include <cmath> @@ -488,7 +488,7 @@ } VideoTrackAdapter::~VideoTrackAdapter() { - DCHECK(adapters_.empty()); + DCHECK(adapters_.IsEmpty()); } void VideoTrackAdapter::AddTrack(const MediaStreamVideoTrack* track, @@ -671,7 +671,7 @@ void VideoTrackAdapter::RemoveTrackOnIO(const MediaStreamVideoTrack* track) { DCHECK(io_task_runner_->BelongsToCurrentThread()); - for (auto it = adapters_.begin(); it != adapters_.end(); ++it) { + for (auto* it = adapters_.begin(); it != adapters_.end(); ++it) { (*it)->RemoveCallbacks(track); if ((*it)->IsEmpty()) { adapters_.erase(it); @@ -687,7 +687,7 @@ VideoFrameResolutionAdapter::VideoTrackCallbacks track_callbacks; // Remove the track. - for (auto it = adapters_.begin(); it != adapters_.end(); ++it) { + for (auto* it = adapters_.begin(); it != adapters_.end(); ++it) { track_callbacks = (*it)->RemoveAndGetCallbacks(track); if (track_callbacks.frame_callback.is_null()) continue; @@ -721,7 +721,7 @@ frame->natural_size().height() == source_frame_size_->width()) { is_device_rotated = true; } - if (adapters_.empty()) { + if (adapters_.IsEmpty()) { renderer_task_runner_->PostTask( FROM_HERE, base::BindOnce(frame_dropped_cb_,
diff --git a/third_party/blink/public/web/modules/mediastream/video_track_adapter.h b/third_party/blink/renderer/modules/mediastream/video_track_adapter.h similarity index 90% rename from third_party/blink/public/web/modules/mediastream/video_track_adapter.h rename to third_party/blink/renderer/modules/mediastream/video_track_adapter.h index 088ea41..76a6710 100644 --- a/third_party/blink/public/web/modules/mediastream/video_track_adapter.h +++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter.h
@@ -2,15 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_VIDEO_TRACK_ADAPTER_H_ -#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_VIDEO_TRACK_ADAPTER_H_ +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_VIDEO_TRACK_ADAPTER_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_VIDEO_TRACK_ADAPTER_H_ #include <stdint.h> -#include <vector> - +#include "base/callback.h" #include "base/macros.h" -#include "base/memory/ref_counted.h" #include "base/optional.h" #include "base/single_thread_task_runner.h" #include "base/time/time.h" @@ -18,7 +16,8 @@ #include "third_party/blink/public/platform/modules/mediastream/media_stream_types.h" #include "third_party/blink/public/platform/web_common.h" #include "third_party/blink/public/web/modules/mediastream/media_stream_video_track.h" -#include "ui/gfx/geometry/size.h" +#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h" +#include "third_party/blink/renderer/platform/wtf/vector.h" namespace blink { @@ -34,9 +33,9 @@ // Adaptations is done by wrapping the original media::VideoFrame in a new // media::VideoFrame with a new visible_rect and natural_size. class BLINK_EXPORT VideoTrackAdapter - : public base::RefCountedThreadSafe<VideoTrackAdapter> { + : public WTF::ThreadSafeRefCounted<VideoTrackAdapter> { public: - using OnMutedCallback = base::Callback<void(bool mute_state)>; + using OnMutedCallback = base::RepeatingCallback<void(bool mute_state)>; VideoTrackAdapter( scoped_refptr<base::SingleThreadTaskRunner> io_task_runner, @@ -90,7 +89,7 @@ private: virtual ~VideoTrackAdapter(); - friend class base::RefCountedThreadSafe<VideoTrackAdapter>; + friend class WTF::ThreadSafeRefCounted<VideoTrackAdapter>; void AddTrackOnIO(const MediaStreamVideoTrack* track, VideoCaptureDeliverFrameCB frame_callback, @@ -127,7 +126,7 @@ // It does the resolution adaptation and delivers frames to all registered // tracks. class VideoFrameResolutionAdapter; - using FrameAdapters = std::vector<scoped_refptr<VideoFrameResolutionAdapter>>; + using FrameAdapters = WTF::Vector<scoped_refptr<VideoFrameResolutionAdapter>>; FrameAdapters adapters_; // Set to true if frame monitoring has been started. It is only accessed on @@ -152,4 +151,4 @@ } // namespace blink -#endif // THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_MEDIASTREAM_VIDEO_TRACK_ADAPTER_H_ +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_VIDEO_TRACK_ADAPTER_H_
diff --git a/content/renderer/media/stream/video_track_adapter_unittest.cc b/third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc similarity index 97% rename from content/renderer/media/stream/video_track_adapter_unittest.cc rename to third_party/blink/renderer/modules/mediastream/video_track_adapter_unittest.cc index 1fae622..4afe674 100644 --- a/content/renderer/media/stream/video_track_adapter_unittest.cc +++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter_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/blink/public/web/modules/mediastream/video_track_adapter.h" +#include "third_party/blink/renderer/modules/mediastream/video_track_adapter.h" #include <limits> @@ -10,10 +10,7 @@ #include "testing/gtest/include/gtest/gtest.h" #include "third_party/blink/public/web/modules/mediastream/video_track_adapter_settings.h" -namespace content { - -using blink::VideoTrackAdapter; -using blink::VideoTrackAdapterSettings; +namespace blink { // Most VideoTrackAdapter functionality is tested in MediaStreamVideoSourceTest. // These tests focus on the computation of cropped frame sizes in edge cases @@ -192,4 +189,4 @@ EXPECT_EQ(desired_size.height(), kInputHeight); } -} // namespace content +} // namespace blink
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc index e8b2c295..bb7c448 100644 --- a/third_party/blink/renderer/modules/modules_initializer.cc +++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -178,7 +178,7 @@ ProvidePushControllerTo(frame, client->PushClient()); ProvideUserMediaTo( frame, std::make_unique<UserMediaClient>(client->UserMediaClient())); - ProvideIndexedDBClientTo(frame, IndexedDBClient::Create(frame)); + ProvideIndexedDBClientTo(frame, MakeGarbageCollected<IndexedDBClient>(frame)); ProvideLocalFileSystemTo(frame, std::make_unique<LocalFileSystemClient>()); NavigatorContentUtils::ProvideTo( *frame.DomWindow()->navigator(), @@ -201,7 +201,7 @@ void ModulesInitializer::ProvideIndexedDBClientToWorker( WorkerClients& worker_clients) const { ::blink::ProvideIndexedDBClientToWorker( - &worker_clients, IndexedDBClient::Create(worker_clients)); + &worker_clients, MakeGarbageCollected<IndexedDBClient>(worker_clients)); } MediaControls* ModulesInitializer::CreateMediaControls(
diff --git a/third_party/blink/renderer/modules/payments/BUILD.gn b/third_party/blink/renderer/modules/payments/BUILD.gn index 8c22515..d9fa9400 100644 --- a/third_party/blink/renderer/modules/payments/BUILD.gn +++ b/third_party/blink/renderer/modules/payments/BUILD.gn
@@ -49,6 +49,8 @@ "payment_state_resolver.h", "payments_validators.cc", "payments_validators.h", + "update_payment_details_function.cc", + "update_payment_details_function.h", ] deps = [
diff --git a/third_party/blink/renderer/modules/payments/payment_request.cc b/third_party/blink/renderer/modules/payments/payment_request.cc index 3895841..83fb32e 100644 --- a/third_party/blink/renderer/modules/payments/payment_request.cc +++ b/third_party/blink/renderer/modules/payments/payment_request.cc
@@ -54,6 +54,7 @@ #include "third_party/blink/renderer/modules/payments/payment_shipping_option.h" #include "third_party/blink/renderer/modules/payments/payment_validation_errors.h" #include "third_party/blink/renderer/modules/payments/payments_validators.h" +#include "third_party/blink/renderer/modules/payments/update_payment_details_function.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/mojo/mojo_helper.h" @@ -210,10 +211,6 @@ namespace blink { namespace { -// If the website does not call complete() 60 seconds after show() has been -// resolved, then behave as if the website called complete("fail"). -constexpr TimeDelta kCompleteTimeout = TimeDelta::FromSeconds(60); - // Validates ShippingOption or PaymentItem, which happen to have identical // fields, except for "id", which is present only in ShippingOption. template <typename T> @@ -791,6 +788,11 @@ PaymentRequest::~PaymentRequest() = default; ScriptPromise PaymentRequest::show(ScriptState* script_state) { + return show(script_state, ScriptPromise()); +} + +ScriptPromise PaymentRequest::show(ScriptState* script_state, + ScriptPromise details_promise) { if (!script_state->ContextIsValid() || !LocalDOMWindow::From(script_state) || !LocalDOMWindow::From(script_state)->GetFrame()) { return ScriptPromise::RejectWithDOMException( @@ -820,7 +822,22 @@ "Page popups are suppressed")); } - payment_provider_->Show(is_user_gesture); + is_waiting_for_show_promise_to_resolve_ = !details_promise.IsEmpty(); + payment_provider_->Show(is_user_gesture, + is_waiting_for_show_promise_to_resolve_); + if (is_waiting_for_show_promise_to_resolve_) { + // If the website does not calculate the final shopping cart contents within + // 10 seconds, abort payment. + update_payment_details_timer_.StartOneShot(TimeDelta::FromSeconds(10), + FROM_HERE); + details_promise.Then( + UpdatePaymentDetailsFunction::CreateFunction( + script_state, this, + UpdatePaymentDetailsFunction::ResolveType::kFulfill), + UpdatePaymentDetailsFunction::CreateFunction( + script_state, this, + UpdatePaymentDetailsFunction::ResolveType::kReject)); + } accept_resolver_ = MakeGarbageCollected<ScriptPromiseResolver>(script_state); return accept_resolver_->Promise(); @@ -1038,8 +1055,13 @@ void PaymentRequest::OnUpdatePaymentDetails( const ScriptValue& details_script_value) { - if (!GetPendingAcceptPromiseResolver() || !payment_provider_) + ScriptPromiseResolver* resolver = GetPendingAcceptPromiseResolver(); + if (!resolver || !payment_provider_ || + !update_payment_details_timer_.IsActive()) { return; + } + + update_payment_details_timer_.Stop(); PaymentDetailsUpdate* details = PaymentDetailsUpdate::Create(); ExceptionState exception_state(v8::Isolate::GetCurrent(), @@ -1048,7 +1070,6 @@ V8PaymentDetailsUpdate::ToImpl(details_script_value.GetIsolate(), details_script_value.V8Value(), details, exception_state); - ScriptPromiseResolver* resolver = GetPendingAcceptPromiseResolver(); if (exception_state.HadException()) { resolver->Reject(exception_state.GetException()); ClearResolversAndCloseMojoConnection(); @@ -1069,10 +1090,36 @@ if (!options_->requestShipping()) validated_details->shipping_options = base::nullopt; + if (is_waiting_for_show_promise_to_resolve_) { + is_waiting_for_show_promise_to_resolve_ = false; + + if (!validated_details->total) { + resolver->Reject( + DOMException::Create(DOMExceptionCode::kInvalidStateError, + "Must specify 'total' when resolving the " + "promise passed into PaymentRequest.show()")); + ClearResolversAndCloseMojoConnection(); + return; + } + + if (!validated_details->error.IsEmpty()) { + resolver->Reject( + DOMException::Create(DOMExceptionCode::kInvalidStateError, + "Cannot specify 'error' when resolving the " + "promise passed into PaymentRequest.show()")); + ClearResolversAndCloseMojoConnection(); + return; + } + } + payment_provider_->UpdateWith(std::move(validated_details)); } void PaymentRequest::OnUpdatePaymentDetailsFailure(const String& error) { + if (!payment_provider_) + return; + if (update_payment_details_timer_.IsActive()) + update_payment_details_timer_.Stop(); ScriptPromiseResolver* resolver = GetPendingAcceptPromiseResolver(); if (resolver) { resolver->Reject( @@ -1108,6 +1155,11 @@ OnCompleteTimeout(nullptr); } +void PaymentRequest::OnUpdatePaymentDetailsTimeoutForTesting() { + update_payment_details_timer_.Stop(); + OnUpdatePaymentDetailsTimeout(nullptr); +} + PaymentRequest::PaymentRequest( ExecutionContext* execution_context, const HeapVector<Member<PaymentMethodData>>& method_data, @@ -1120,7 +1172,12 @@ complete_timer_( execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI), this, - &PaymentRequest::OnCompleteTimeout) { + &PaymentRequest::OnCompleteTimeout), + update_payment_details_timer_( + execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI), + this, + &PaymentRequest::OnUpdatePaymentDetailsTimeout), + is_waiting_for_show_promise_to_resolve_(false) { DCHECK(GetExecutionContext()->IsSecureContext()); if (!AllowedToUsePaymentRequest(execution_context)) { @@ -1307,7 +1364,9 @@ return; } - complete_timer_.StartOneShot(kCompleteTimeout, FROM_HERE); + // If the website does not call complete() 60 seconds after show() has been + // resolved, then behave as if the website called complete("fail"). + complete_timer_.StartOneShot(TimeDelta::FromSeconds(60), FROM_HERE); if (retry_resolver_) { DCHECK(payment_response_); @@ -1515,6 +1574,14 @@ ClearResolversAndCloseMojoConnection(); } +void PaymentRequest::OnUpdatePaymentDetailsTimeout(TimerBase*) { + OnUpdatePaymentDetailsFailure( + is_waiting_for_show_promise_to_resolve_ + ? "Timed out waiting for a PaymentRequest.show(promise) to resolve." + : "Timed out waiting for a " + "PaymentRequestUpdateEvent.updateWith(promise) to resolve."); +} + void PaymentRequest::ClearResolversAndCloseMojoConnection() { complete_timer_.Stop(); complete_resolver_.Clear(); @@ -1537,15 +1604,21 @@ PaymentRequestUpdateEvent* event) { event->SetTarget(event_target); event->SetPaymentRequest(this); + + // If the website does not calculate the updated shopping cart contents + // within 60 seconds, abort payment. + update_payment_details_timer_.StartOneShot(TimeDelta::FromSeconds(60), + FROM_HERE); + event_target->DispatchEvent(*event); if (!event->is_waiting_for_update()) { // DispatchEvent runs synchronously. The method is_waiting_for_update() - // returns true if the merchant called event.updateWith() within the event - // handler. Calling this method is optional. If the method is not called, - // the renderer sends a message to the browser to re-enable UI interactions. + // returns false if the merchant did not call event.updateWith() within the + // event handler, which is optional, so the renderer sends a message to the + // browser to re-enable UI interactions. const String& message = String::Format( - "No updateWith() call in '%s' event handler. User " - "may see outdated line items and total.", + "No updateWith() call in '%s' event handler. User may see outdated " + "line items and total.", event->type().Ascii().data()); GetExecutionContext()->AddConsoleMessage( ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript,
diff --git a/third_party/blink/renderer/modules/payments/payment_request.h b/third_party/blink/renderer/modules/payments/payment_request.h index b7f7cc2..49a5dde27 100644 --- a/third_party/blink/renderer/modules/payments/payment_request.h +++ b/third_party/blink/renderer/modules/payments/payment_request.h
@@ -67,6 +67,7 @@ ~PaymentRequest() override; ScriptPromise show(ScriptState*); + ScriptPromise show(ScriptState*, ScriptPromise details_promise); ScriptPromise abort(ScriptState*); const String& id() const { return id_; } @@ -100,6 +101,7 @@ void Trace(blink::Visitor*) override; void OnCompleteTimeoutForTesting(); + void OnUpdatePaymentDetailsTimeoutForTesting(); enum { // Implementation defined constants controlling the allowed list length @@ -132,6 +134,7 @@ void WarnNoFavicon() override; void OnCompleteTimeout(TimerBase*); + void OnUpdatePaymentDetailsTimeout(TimerBase*); // Clears the promise resolvers and closes the Mojo connection. void ClearResolversAndCloseMojoConnection(); @@ -163,6 +166,8 @@ payments::mojom::blink::PaymentRequestPtr payment_provider_; mojo::Binding<payments::mojom::blink::PaymentRequestClient> client_binding_; TaskRunnerTimer<PaymentRequest> complete_timer_; + TaskRunnerTimer<PaymentRequest> update_payment_details_timer_; + bool is_waiting_for_show_promise_to_resolve_; DISALLOW_COPY_AND_ASSIGN(PaymentRequest); };
diff --git a/third_party/blink/renderer/modules/payments/payment_request.idl b/third_party/blink/renderer/modules/payments/payment_request.idl index e2a1c83d..97b3655 100644 --- a/third_party/blink/renderer/modules/payments/payment_request.idl +++ b/third_party/blink/renderer/modules/payments/payment_request.idl
@@ -14,7 +14,7 @@ Exposed=Window, ActiveScriptWrappable ] interface PaymentRequest : EventTarget { - [CallWith=ScriptState, NewObject] Promise<PaymentResponse> show(); + [CallWith=ScriptState, NewObject] Promise<PaymentResponse> show(optional Promise<PaymentDetailsUpdate> detailsPromise); [CallWith=ScriptState, NewObject] Promise<void> abort(); [CallWith=ScriptState, HighEntropy, Measure, NewObject] Promise<boolean> canMakePayment(); [CallWith=ScriptState, HighEntropy, Measure, NewObject, RuntimeEnabled=PaymentRequestHasEnrolledInstrument] Promise<boolean> hasEnrolledInstrument();
diff --git a/third_party/blink/renderer/modules/payments/payment_request_delegate.h b/third_party/blink/renderer/modules/payments/payment_request_delegate.h index 49dd9ad..91abd7d 100644 --- a/third_party/blink/renderer/modules/payments/payment_request_delegate.h +++ b/third_party/blink/renderer/modules/payments/payment_request_delegate.h
@@ -13,11 +13,21 @@ class ScriptValue; +// The interface for updating the payment details (shopping cart, shipping +// options, total) in response to shipping address or option change, or through +// the promise passed into the PaymentRequest.show() method. class MODULES_EXPORT PaymentRequestDelegate : public GarbageCollectedMixin { public: + // Updates the payment details in response to a change in, e.g., shipping + // address. This stops the spinner in the UI. virtual void OnUpdatePaymentDetails( const ScriptValue& details_script_value) = 0; + + // Called when the merchant failed to update the payment details in response + // to a change in, e.g., shipping address. This will abort the payment. virtual void OnUpdatePaymentDetailsFailure(const String& error) = 0; + + // Whether the PaymentRequest.show() or PaymentResponse.retry() is ongoing. virtual bool IsInteractive() const = 0; protected:
diff --git a/third_party/blink/renderer/modules/payments/payment_request_test.cc b/third_party/blink/renderer/modules/payments/payment_request_test.cc index 2be918d..8f6e899b502 100644 --- a/third_party/blink/renderer/modules/payments/payment_request_test.cc +++ b/third_party/blink/renderer/modules/payments/payment_request_test.cc
@@ -370,6 +370,8 @@ request->show(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message)); + static_cast<payments::mojom::blink::PaymentRequestClient*>(request) + ->OnShippingAddressChange(BuildPaymentAddressForTest()); request->OnUpdatePaymentDetailsFailure("oops"); v8::MicrotasksScope::PerformCheckpoint(scope.GetScriptState()->GetIsolate()); @@ -405,6 +407,8 @@ request->show(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectCall()); + static_cast<payments::mojom::blink::PaymentRequestClient*>(request) + ->OnShippingAddressChange(BuildPaymentAddressForTest()); request->OnUpdatePaymentDetails( ScriptValue::From(scope.GetScriptState(), "NotPaymentDetails")); } @@ -421,6 +425,8 @@ request->show(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectCall()); + static_cast<payments::mojom::blink::PaymentRequestClient*>(request) + ->OnShippingAddressChange(BuildPaymentAddressForTest()); request->OnUpdatePaymentDetails( ScriptValue::From( scope.GetScriptState(), @@ -446,6 +452,8 @@ EXPECT_TRUE(request->shippingOption().IsNull()); request->show(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectNoCall()); + static_cast<payments::mojom::blink::PaymentRequestClient*>(request) + ->OnShippingAddressChange(BuildPaymentAddressForTest()); String detail_with_shipping_options = "{\"total\": {\"label\": \"Total\", \"amount\": {\"currency\": \"USD\", " "\"value\": \"5.00\"}}," @@ -460,6 +468,8 @@ scope.GetExceptionState()))); EXPECT_FALSE(scope.GetExceptionState().HadException()); EXPECT_EQ("standardShippingOption", request->shippingOption()); + static_cast<payments::mojom::blink::PaymentRequestClient*>(request) + ->OnShippingAddressChange(BuildPaymentAddressForTest()); String detail_without_shipping_options = "{\"total\": {\"label\": \"Total\", \"amount\": {\"currency\": \"USD\", " "\"value\": \"5.00\"}}}"; @@ -519,6 +529,8 @@ EXPECT_FALSE(scope.GetExceptionState().HadException()); request->show(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectNoCall()); + static_cast<payments::mojom::blink::PaymentRequestClient*>(request) + ->OnShippingAddressChange(BuildPaymentAddressForTest()); String detail = "{\"total\": {\"label\": \"Total\", \"amount\": {\"currency\": \"USD\", " "\"value\": \"5.00\"}},"
diff --git a/third_party/blink/renderer/modules/payments/payment_request_update_event.cc b/third_party/blink/renderer/modules/payments/payment_request_update_event.cc index 44fafee..7af3e8c 100644 --- a/third_party/blink/renderer/modules/payments/payment_request_update_event.cc +++ b/third_party/blink/renderer/modules/payments/payment_request_update_event.cc
@@ -11,71 +11,11 @@ #include "third_party/blink/renderer/core/dom/dom_exception.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/modules/payments/payment_request_delegate.h" +#include "third_party/blink/renderer/modules/payments/update_payment_details_function.h" #include "third_party/blink/renderer/platform/bindings/exception_state.h" #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" namespace blink { -namespace { - -// Reject the payment request if the page does not resolve the promise from -// updateWith within 60 seconds. -constexpr TimeDelta kAbortTimeout = TimeDelta::FromSeconds(60); - -} // anonymous namespace - -class PaymentRequestUpdateEvent::UpdatePaymentDetailsFunction final - : public ScriptFunction { - public: - enum class ResolveType { - kFulfilled, - kRejected, - }; - - static v8::Local<v8::Function> CreateFunction( - ScriptState* script_state, - ResolveType resolve_type, - PaymentRequestUpdateEvent* event) { - UpdatePaymentDetailsFunction* self = - MakeGarbageCollected<UpdatePaymentDetailsFunction>(script_state, - resolve_type, event); - return self->BindToV8Function(); - } - - UpdatePaymentDetailsFunction(ScriptState* script_state, - ResolveType resolve_type, - PaymentRequestUpdateEvent* event) - : ScriptFunction(script_state), - resolve_type_(resolve_type), - event_(event) { - DCHECK(event_); - } - - void Trace(blink::Visitor* visitor) override { - visitor->Trace(event_); - ScriptFunction::Trace(visitor); - } - - private: - ScriptValue Call(ScriptValue value) override { - if (!event_ || !event_->request_) - return ScriptValue(); - - event_->abort_timer_.Stop(); - if (resolve_type_ == ResolveType::kFulfilled) { - event_->request_->OnUpdatePaymentDetails(value); - } else if (resolve_type_ == ResolveType::kRejected) { - event_->request_->OnUpdatePaymentDetailsFailure( - ToCoreString(value.V8Value() - ->ToString(GetScriptState()->GetContext()) - .ToLocalChecked())); - } - event_->SetPaymentRequest(nullptr); - return ScriptValue(); - } - - ResolveType resolve_type_; - Member<PaymentRequestUpdateEvent> event_; -}; PaymentRequestUpdateEvent::~PaymentRequestUpdateEvent() = default; @@ -122,15 +62,12 @@ stopImmediatePropagation(); wait_for_update_ = true; - DCHECK(!abort_timer_.IsActive()); - abort_timer_.StartOneShot(kAbortTimeout, FROM_HERE); - promise.Then(UpdatePaymentDetailsFunction::CreateFunction( - script_state, - UpdatePaymentDetailsFunction::ResolveType::kFulfilled, this), + script_state, request_, + UpdatePaymentDetailsFunction::ResolveType::kFulfill), UpdatePaymentDetailsFunction::CreateFunction( - script_state, - UpdatePaymentDetailsFunction::ResolveType::kRejected, this)); + script_state, request_, + UpdatePaymentDetailsFunction::ResolveType::kReject)); } void PaymentRequestUpdateEvent::Trace(blink::Visitor* visitor) { @@ -138,27 +75,10 @@ Event::Trace(visitor); } -void PaymentRequestUpdateEvent::OnUpdateEventTimeoutForTesting() { - OnUpdateEventTimeout(nullptr); -} - PaymentRequestUpdateEvent::PaymentRequestUpdateEvent( ExecutionContext* execution_context, const AtomicString& type, const PaymentRequestUpdateEventInit* init) - : Event(type, init), - wait_for_update_(false), - abort_timer_(execution_context->GetTaskRunner(TaskType::kUserInteraction), - this, - &PaymentRequestUpdateEvent::OnUpdateEventTimeout) {} - -void PaymentRequestUpdateEvent::OnUpdateEventTimeout(TimerBase*) { - if (!request_) - return; - abort_timer_.Stop(); - request_->OnUpdatePaymentDetailsFailure( - "Timed out waiting for a response to a '" + type() + "' event"); - SetPaymentRequest(nullptr); -} + : Event(type, init), wait_for_update_(false) {} } // namespace blink
diff --git a/third_party/blink/renderer/modules/payments/payment_request_update_event.h b/third_party/blink/renderer/modules/payments/payment_request_update_event.h index 24dea88..f3e5e046 100644 --- a/third_party/blink/renderer/modules/payments/payment_request_update_event.h +++ b/third_party/blink/renderer/modules/payments/payment_request_update_event.h
@@ -46,20 +46,11 @@ void Trace(blink::Visitor*) override; - void OnUpdateEventTimeoutForTesting(); - private: - // This class is declared here because it requires privileges to access some - // PaymentRequestUpdateEvent's member fields, such as request_, abort_timer_. - class UpdatePaymentDetailsFunction; - - void OnUpdateEventTimeout(TimerBase*); - // True after event.updateWith() was called. bool wait_for_update_; Member<PaymentRequestDelegate> request_; - TaskRunnerTimer<PaymentRequestUpdateEvent> abort_timer_; }; } // namespace blink
diff --git a/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc b/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc index ddd7fab1..ca4d769 100644 --- a/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc +++ b/third_party/blink/renderer/modules/payments/payment_request_update_event_test.cc
@@ -151,12 +151,14 @@ request->show(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message)); - event->OnUpdateEventTimeoutForTesting(); + static_cast<payments::mojom::blink::PaymentRequestClient*>(request) + ->OnShippingAddressChange(BuildPaymentAddressForTest()); + request->OnUpdatePaymentDetailsTimeoutForTesting(); v8::MicrotasksScope::PerformCheckpoint(scope.GetScriptState()->GetIsolate()); EXPECT_EQ( - "AbortError: Timed out waiting for a response to a " - "'shippingaddresschange' event", + "AbortError: Timed out waiting for a " + "PaymentRequestUpdateEvent.updateWith(promise) to resolve.", error_message); event->updateWith( @@ -165,7 +167,9 @@ ->Promise(), scope.GetExceptionState()); - EXPECT_FALSE(scope.GetExceptionState().HadException()); + EXPECT_TRUE(scope.GetExceptionState().HadException()); + EXPECT_EQ("PaymentRequest is no longer interactive", + scope.GetExceptionState().Message()); } TEST(PaymentRequestUpdateEventTest, OptionChangeUpdateWithTimeout) { @@ -185,12 +189,14 @@ request->show(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message)); - event->OnUpdateEventTimeoutForTesting(); + static_cast<payments::mojom::blink::PaymentRequestClient*>(request) + ->OnShippingAddressChange(BuildPaymentAddressForTest()); + request->OnUpdatePaymentDetailsTimeoutForTesting(); v8::MicrotasksScope::PerformCheckpoint(scope.GetScriptState()->GetIsolate()); EXPECT_EQ( - "AbortError: Timed out waiting for a response to a " - "'shippingoptionchange' event", + "AbortError: Timed out waiting for a " + "PaymentRequestUpdateEvent.updateWith(promise) to resolve.", error_message); event->updateWith( @@ -199,7 +205,9 @@ ->Promise(), scope.GetExceptionState()); - EXPECT_FALSE(scope.GetExceptionState().HadException()); + EXPECT_TRUE(scope.GetExceptionState().HadException()); + EXPECT_EQ("PaymentRequest is no longer interactive", + scope.GetExceptionState().Message()); } TEST(PaymentRequestUpdateEventTest, AddressChangePromiseTimeout) { @@ -215,21 +223,23 @@ event->SetTrusted(true); event->SetPaymentRequest(request); event->SetEventPhase(Event::kCapturingPhase); - auto* payment_details = - MakeGarbageCollected<ScriptPromiseResolver>(scope.GetScriptState()); String error_message; request->show(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message)); + static_cast<payments::mojom::blink::PaymentRequestClient*>(request) + ->OnShippingAddressChange(BuildPaymentAddressForTest()); + auto* payment_details = + MakeGarbageCollected<ScriptPromiseResolver>(scope.GetScriptState()); event->updateWith(scope.GetScriptState(), payment_details->Promise(), scope.GetExceptionState()); EXPECT_FALSE(scope.GetExceptionState().HadException()); - event->OnUpdateEventTimeoutForTesting(); + request->OnUpdatePaymentDetailsTimeoutForTesting(); v8::MicrotasksScope::PerformCheckpoint(scope.GetScriptState()->GetIsolate()); EXPECT_EQ( - "AbortError: Timed out waiting for a response to a " - "'shippingaddresschange' event", + "AbortError: Timed out waiting for a " + "PaymentRequestUpdateEvent.updateWith(promise) to resolve.", error_message); payment_details->Resolve("foo"); @@ -248,21 +258,23 @@ event->SetTrusted(true); event->SetPaymentRequest(request); event->SetEventPhase(Event::kCapturingPhase); - auto* payment_details = - MakeGarbageCollected<ScriptPromiseResolver>(scope.GetScriptState()); String error_message; request->show(scope.GetScriptState()) .Then(funcs.ExpectNoCall(), funcs.ExpectCall(&error_message)); + static_cast<payments::mojom::blink::PaymentRequestClient*>(request) + ->OnShippingAddressChange(BuildPaymentAddressForTest()); + auto* payment_details = + MakeGarbageCollected<ScriptPromiseResolver>(scope.GetScriptState()); event->updateWith(scope.GetScriptState(), payment_details->Promise(), scope.GetExceptionState()); EXPECT_FALSE(scope.GetExceptionState().HadException()); - event->OnUpdateEventTimeoutForTesting(); + request->OnUpdatePaymentDetailsTimeoutForTesting(); v8::MicrotasksScope::PerformCheckpoint(scope.GetScriptState()->GetIsolate()); EXPECT_EQ( - "AbortError: Timed out waiting for a response to a " - "'shippingoptionchange' event", + "AbortError: Timed out waiting for a " + "PaymentRequestUpdateEvent.updateWith(promise) to resolve.", error_message); payment_details->Resolve("foo");
diff --git a/third_party/blink/renderer/modules/payments/payment_test_helper.cc b/third_party/blink/renderer/modules/payments/payment_test_helper.cc index 2b206afb..e4126f5a 100644 --- a/third_party/blink/renderer/modules/payments/payment_test_helper.cc +++ b/third_party/blink/renderer/modules/payments/payment_test_helper.cc
@@ -205,6 +205,13 @@ return result; } +payments::mojom::blink::PaymentAddressPtr BuildPaymentAddressForTest() { + payments::mojom::blink::PaymentAddressPtr result = + payments::mojom::blink::PaymentAddress::New(); + result->country = "US"; + return result; +} + void MakePaymentRequestOriginSecure(Document& document) { document.SetSecurityOrigin( SecurityOrigin::Create(KURL("https://www.example.com/")));
diff --git a/third_party/blink/renderer/modules/payments/payment_test_helper.h b/third_party/blink/renderer/modules/payments/payment_test_helper.h index b9bd4fad..1042389 100644 --- a/third_party/blink/renderer/modules/payments/payment_test_helper.h +++ b/third_party/blink/renderer/modules/payments/payment_test_helper.h
@@ -85,6 +85,8 @@ payments::mojom::blink::PaymentResponsePtr BuildPaymentResponseForTest(); +payments::mojom::blink::PaymentAddressPtr BuildPaymentAddressForTest(); + void MakePaymentRequestOriginSecure(Document&); class PaymentRequestMockFunctionScope {
diff --git a/third_party/blink/renderer/modules/payments/update_payment_details_function.cc b/third_party/blink/renderer/modules/payments/update_payment_details_function.cc new file mode 100644 index 0000000..3cdf2fb --- /dev/null +++ b/third_party/blink/renderer/modules/payments/update_payment_details_function.cc
@@ -0,0 +1,57 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/renderer/modules/payments/update_payment_details_function.h" + +#include "third_party/blink/renderer/bindings/core/v8/script_value.h" +#include "third_party/blink/renderer/modules/payments/payment_request_delegate.h" + +namespace blink { + +// static +v8::Local<v8::Function> UpdatePaymentDetailsFunction::CreateFunction( + ScriptState* script_state, + PaymentRequestDelegate* delegate, + ResolveType resolve_type) { + UpdatePaymentDetailsFunction* self = + MakeGarbageCollected<UpdatePaymentDetailsFunction>(script_state, delegate, + resolve_type); + return self->BindToV8Function(); +} + +UpdatePaymentDetailsFunction::UpdatePaymentDetailsFunction( + ScriptState* script_state, + PaymentRequestDelegate* delegate, + ResolveType resolve_type) + : ScriptFunction(script_state), + delegate_(delegate), + resolve_type_(resolve_type) { + DCHECK(delegate_); +} + +void UpdatePaymentDetailsFunction::Trace(blink::Visitor* visitor) { + visitor->Trace(delegate_); + ScriptFunction::Trace(visitor); +} + +ScriptValue UpdatePaymentDetailsFunction::Call(ScriptValue value) { + if (!delegate_) + return ScriptValue(); + + switch (resolve_type_) { + case ResolveType::kFulfill: + delegate_->OnUpdatePaymentDetails(value); + break; + case ResolveType::kReject: + delegate_->OnUpdatePaymentDetailsFailure( + ToCoreString(value.V8Value() + ->ToString(GetScriptState()->GetContext()) + .ToLocalChecked())); + break; + } + delegate_ = nullptr; + return ScriptValue(); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/payments/update_payment_details_function.h b/third_party/blink/renderer/modules/payments/update_payment_details_function.h new file mode 100644 index 0000000..11d32ba1 --- /dev/null +++ b/third_party/blink/renderer/modules/payments/update_payment_details_function.h
@@ -0,0 +1,41 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_UPDATE_PAYMENT_DETAILS_FUNCTION_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_UPDATE_PAYMENT_DETAILS_FUNCTION_H_ + +#include "third_party/blink/renderer/bindings/core/v8/script_function.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" + +namespace blink { + +class PaymentRequestDelegate; +class ScriptState; +class ScriptValue; + +class UpdatePaymentDetailsFunction : public ScriptFunction { + public: + enum class ResolveType { + kFulfill, + kReject, + }; + + static v8::Local<v8::Function> CreateFunction(ScriptState*, + PaymentRequestDelegate*, + ResolveType); + + UpdatePaymentDetailsFunction(ScriptState*, + PaymentRequestDelegate*, + ResolveType); + void Trace(blink::Visitor*) override; + ScriptValue Call(ScriptValue) override; + + private: + Member<PaymentRequestDelegate> delegate_; + ResolveType resolve_type_; +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_PAYMENTS_UPDATE_PAYMENT_DETAILS_FUNCTION_H_
diff --git a/third_party/blink/renderer/modules/presentation/presentation_request.cc b/third_party/blink/renderer/modules/presentation/presentation_request.cc index e967c09..33c4fc8 100644 --- a/third_party/blink/renderer/modules/presentation/presentation_request.cc +++ b/third_party/blink/renderer/modules/presentation/presentation_request.cc
@@ -59,7 +59,7 @@ const Vector<String>& urls, ExceptionState& exception_state) { if (To<Document>(execution_context) - ->IsSandboxed(kSandboxPresentationController)) { + ->IsSandboxed(WebSandboxFlags::kPresentationController)) { exception_state.ThrowSecurityError( "The document is sandboxed and lacks the 'allow-presentation' flag."); return nullptr;
diff --git a/third_party/blink/renderer/modules/screen_orientation/screen_orientation.cc b/third_party/blink/renderer/modules/screen_orientation/screen_orientation.cc index d4f68b30..59c16d8 100644 --- a/third_party/blink/renderer/modules/screen_orientation/screen_orientation.cc +++ b/third_party/blink/renderer/modules/screen_orientation/screen_orientation.cc
@@ -161,7 +161,7 @@ return promise; } - if (document->IsSandboxed(kSandboxOrientationLock)) { + if (document->IsSandboxed(WebSandboxFlags::kOrientationLock)) { DOMException* exception = DOMException::Create(DOMExceptionCode::kSecurityError, "The document is sandboxed and lacks the "
diff --git a/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc b/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc index 7f43d54..eb0a2d7f 100644 --- a/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc +++ b/third_party/blink/renderer/modules/service_worker/navigator_service_worker.cc
@@ -90,7 +90,7 @@ ->GetSecurityOrigin() ->CanAccessServiceWorkers()) { String error_message; - if (frame->GetSecurityContext()->IsSandboxed(kSandboxOrigin)) { + if (frame->GetSecurityContext()->IsSandboxed(WebSandboxFlags::kOrigin)) { error_message = "Service worker is disabled because the context is sandboxed and " "lacks the 'allow-same-origin' flag.";
diff --git a/third_party/blink/renderer/modules/storage/dom_window_storage.cc b/third_party/blink/renderer/modules/storage/dom_window_storage.cc index a03053b..80046d5 100644 --- a/third_party/blink/renderer/modules/storage/dom_window_storage.cc +++ b/third_party/blink/renderer/modules/storage/dom_window_storage.cc
@@ -64,7 +64,7 @@ DCHECK(document); String access_denied_message = "Access is denied for this document."; if (!document->GetSecurityOrigin()->CanAccessSessionStorage()) { - if (document->IsSandboxed(kSandboxOrigin)) + if (document->IsSandboxed(WebSandboxFlags::kOrigin)) exception_state.ThrowSecurityError( "The document is sandboxed and lacks the 'allow-same-origin' flag."); else if (document->Url().ProtocolIs("data")) @@ -123,7 +123,7 @@ DCHECK(document); String access_denied_message = "Access is denied for this document."; if (!document->GetSecurityOrigin()->CanAccessLocalStorage()) { - if (document->IsSandboxed(kSandboxOrigin)) + if (document->IsSandboxed(WebSandboxFlags::kOrigin)) exception_state.ThrowSecurityError( "The document is sandboxed and lacks the 'allow-same-origin' flag."); else if (document->Url().ProtocolIs("data"))
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn index 9384159..4bb9e4a25 100644 --- a/third_party/blink/renderer/platform/BUILD.gn +++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -551,6 +551,7 @@ "exported/web_network_state_notifier.cc", "exported/web_prerender.cc", "exported/web_prerendering_support.cc", + "exported/web_resource_timing_info.cc", "exported/web_rtc_answer_options.cc", "exported/web_rtc_ice_candidate.cc", "exported/web_rtc_offer_options.cc", @@ -2125,6 +2126,7 @@ # Tests migrated from the web/tests directory. "exported/web_image_test.cc", + "exported/web_resource_timing_info_test.cc", "exported/web_url_request_test.cc", "exported/web_url_response_test.cc", "timer_perf_test.cc",
diff --git a/third_party/blink/renderer/platform/exported/web_resource_timing_info.cc b/third_party/blink/renderer/platform/exported/web_resource_timing_info.cc new file mode 100644 index 0000000..fc4a988 --- /dev/null +++ b/third_party/blink/renderer/platform/exported/web_resource_timing_info.cc
@@ -0,0 +1,92 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/public/platform/web_resource_timing_info.h" + +#include "third_party/blink/public/platform/web_url_load_timing.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +namespace { + +bool IsSameServerTimingInfo(const WebVector<WebServerTimingInfo>& lhs, + const WebVector<WebServerTimingInfo>& rhs) { + if (lhs.size() != rhs.size()) + return false; + for (size_t i = 0; i < lhs.size(); ++i) { + if (lhs[i] != rhs[i]) + return false; + } + return true; +} + +} // namespace + +bool WebServerTimingInfo::operator==(const WebServerTimingInfo& other) const { + return name == other.name && duration == other.duration && + description == other.description; +} + +bool WebServerTimingInfo::operator!=(const WebServerTimingInfo& other) const { + return !(*this == other); +} + +bool WebResourceTimingInfo::operator==( + const WebResourceTimingInfo& other) const { + return name == other.name && start_time == other.start_time && + alpn_negotiated_protocol == other.alpn_negotiated_protocol && + connection_info == other.connection_info && timing == other.timing && + last_redirect_end_time == other.last_redirect_end_time && + response_end == other.response_end && + transfer_size == other.transfer_size && + encoded_body_size == other.encoded_body_size && + decoded_body_size == other.decoded_body_size && + did_reuse_connection == other.did_reuse_connection && + is_secure_context == other.is_secure_context && + allow_timing_details == other.allow_timing_details && + allow_redirect_details == other.allow_redirect_details && + allow_negative_values == other.allow_negative_values && + IsSameServerTimingInfo(server_timing, other.server_timing); +} + +CrossThreadCopier<WebResourceTimingInfo>::Type CrossThreadCopier< + WebResourceTimingInfo>::Copy(const WebResourceTimingInfo& info) { + WebResourceTimingInfo copy; + + copy.name = String(info.name).IsolatedCopy(); + copy.start_time = info.start_time; + + copy.alpn_negotiated_protocol = + String(info.alpn_negotiated_protocol).IsolatedCopy(); + copy.connection_info = String(info.connection_info).IsolatedCopy(); + + if (!info.timing.IsNull()) + copy.timing = CrossThreadCopier<WebURLLoadTiming>::Copy(info.timing); + + copy.last_redirect_end_time = info.last_redirect_end_time; + copy.response_end = info.response_end; + + copy.transfer_size = info.transfer_size; + copy.encoded_body_size = info.encoded_body_size; + copy.decoded_body_size = info.decoded_body_size; + + copy.did_reuse_connection = info.did_reuse_connection; + copy.is_secure_context = info.is_secure_context; + + copy.allow_timing_details = info.allow_timing_details; + copy.allow_redirect_details = info.allow_redirect_details; + + copy.allow_negative_values = info.allow_negative_values; + for (auto& entry : info.server_timing) { + WebServerTimingInfo entry_copy(String(entry.name).IsolatedCopy(), + entry.duration, + String(entry.description).IsolatedCopy()); + copy.server_timing.emplace_back(std::move(entry_copy)); + } + + return copy; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/exported/web_resource_timing_info_test.cc b/third_party/blink/renderer/platform/exported/web_resource_timing_info_test.cc new file mode 100644 index 0000000..c0e61fac --- /dev/null +++ b/third_party/blink/renderer/platform/exported/web_resource_timing_info_test.cc
@@ -0,0 +1,128 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "third_party/blink/public/platform/web_resource_timing_info.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/blink/renderer/platform/cross_thread_functional.h" +#include "third_party/blink/renderer/platform/loader/fetch/resource_load_timing.h" +#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h" +#include "third_party/blink/renderer/platform/scheduler/public/thread.h" +#include "third_party/blink/renderer/platform/testing/testing_platform_support_with_mock_scheduler.h" + +namespace blink { + +namespace { + +scoped_refptr<ResourceLoadTiming> CreateResourceLoadTiming( + const base::TimeTicks pseudo_time) { + auto timing = ResourceLoadTiming::Create(); + timing->SetRequestTime(pseudo_time); + timing->SetProxyStart(pseudo_time); + timing->SetProxyEnd(pseudo_time); + timing->SetDnsStart(pseudo_time); + timing->SetDnsEnd(pseudo_time); + timing->SetConnectStart(pseudo_time); + timing->SetConnectEnd(pseudo_time); + timing->SetWorkerStart(pseudo_time); + timing->SetWorkerReady(pseudo_time); + timing->SetSendStart(pseudo_time); + timing->SetSendEnd(pseudo_time); + timing->SetReceiveHeadersStart(pseudo_time); + timing->SetReceiveHeadersEnd(pseudo_time); + timing->SetSslStart(pseudo_time); + timing->SetSslStart(pseudo_time); + timing->SetSslEnd(pseudo_time); + timing->SetPushEnd(pseudo_time); + return timing; +} + +WebResourceTimingInfo CreateWebResourceTimingInfo( + const base::TimeTicks pseudo_time) { + WebVector<WebServerTimingInfo> server_timing; + server_timing.emplace_back(WebServerTimingInfo("server_timing_name", 1.0, + "server_timing_description")); + + WebResourceTimingInfo info = { + .name = "name", + .start_time = pseudo_time, + + .alpn_negotiated_protocol = "protocol", + .connection_info = "info", + + .timing = CreateResourceLoadTiming(pseudo_time), + .last_redirect_end_time = pseudo_time, + .response_end = pseudo_time, + + .transfer_size = 1, + .encoded_body_size = 2, + .decoded_body_size = 3, + + .did_reuse_connection = true, + .is_secure_context = true, + + .allow_timing_details = true, + .allow_redirect_details = true, + + .allow_negative_values = true, + + .server_timing = server_timing, + }; + return info; +} + +void CheckWebResourceTimingInfoOnThread(const WebResourceTimingInfo& info, + const base::TimeTicks pseudo_time) { + WebResourceTimingInfo expected = CreateWebResourceTimingInfo(pseudo_time); + EXPECT_EQ(expected, info); + + EXPECT_EQ("name", info.name); + EXPECT_EQ(pseudo_time, info.start_time); + + EXPECT_EQ("protocol", info.alpn_negotiated_protocol); + EXPECT_EQ("info", info.connection_info); + + WebURLLoadTiming expected_timing(CreateResourceLoadTiming(pseudo_time)); + EXPECT_EQ(expected_timing, info.timing); + EXPECT_EQ(pseudo_time, info.last_redirect_end_time); + EXPECT_EQ(pseudo_time, info.response_end); + + EXPECT_EQ(1u, info.transfer_size); + EXPECT_EQ(2u, info.encoded_body_size); + EXPECT_EQ(3u, info.decoded_body_size); + + EXPECT_TRUE(info.did_reuse_connection); + EXPECT_TRUE(info.is_secure_context); + + EXPECT_TRUE(info.allow_timing_details); + EXPECT_TRUE(info.allow_redirect_details); + + EXPECT_TRUE(info.allow_negative_values); + + EXPECT_EQ(1u, info.server_timing.size()); + + auto& entry = info.server_timing[0]; + EXPECT_EQ("server_timing_name", entry.name); + EXPECT_EQ(1.0, entry.duration); + EXPECT_EQ("server_timing_description", entry.description); +} + +} // namespace + +TEST(WebResourceTimingInfoTest, CrossThreadCopy) { + ScopedTestingPlatformSupport<TestingPlatformSupportWithMockScheduler> + platform; + + base::TimeTicks pseudo_time = TimeTicks::Now(); + WebResourceTimingInfo info = CreateWebResourceTimingInfo(pseudo_time); + + std::unique_ptr<Thread> thread = Platform::Current()->CreateThread( + ThreadCreationParams(WebThreadType::kTestThread) + .SetThreadNameForTest("TestThread")); + PostCrossThreadTask( + *thread->GetTaskRunner(), FROM_HERE, + CrossThreadBind(&CheckWebResourceTimingInfoOnThread, info, pseudo_time)); +} + +} // namespace blink
diff --git a/third_party/blink/renderer/platform/exported/web_url_load_timing.cc b/third_party/blink/renderer/platform/exported/web_url_load_timing.cc index 82042f97..421bf0e 100644 --- a/third_party/blink/renderer/platform/exported/web_url_load_timing.cc +++ b/third_party/blink/renderer/platform/exported/web_url_load_timing.cc
@@ -196,4 +196,17 @@ return private_.Get(); } +WebURLLoadTiming WebURLLoadTiming::DeepCopy() const { + return private_->DeepCopy(); +} + +CrossThreadCopier<WebURLLoadTiming>::Type +CrossThreadCopier<WebURLLoadTiming>::Copy(const WebURLLoadTiming& timing) { + return timing.DeepCopy(); +} + +bool WebURLLoadTiming::operator==(const WebURLLoadTiming& other) const { + return *private_ == *other.private_; +} + } // namespace blink
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc index 714d8df..299aa53 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc +++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher_test.cc
@@ -114,7 +114,7 @@ void DidReceiveResponse(uint64_t identifier, const ResourceRequest& request, const ResourceResponse& response, - Resource* resource, + const Resource* resource, ResponseSource source) override {} void DidReceiveData(uint64_t identifier, base::span<const char> chunk) override {}
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h b/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h index a51666bd..e074443 100644 --- a/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h +++ b/third_party/blink/renderer/platform/loader/fetch/resource_load_observer.h
@@ -49,11 +49,10 @@ // the memory cache |request| and |resource->GetResourceRequest()| don't // match. |response| may not yet be set to |resource| when this function is // called. - // TODO(yhirano): Use const* Resource. virtual void DidReceiveResponse(uint64_t identifier, const ResourceRequest& request, const ResourceResponse& response, - Resource* resource, + const Resource* resource, ResponseSource) = 0; // Called when a response body chunk is received.
diff --git a/third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h b/third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h index de0c404..76b9df3 100644 --- a/third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h +++ b/third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h
@@ -46,8 +46,6 @@ DISALLOW_NEW(); public: - using value_type = const char; - StringUTF8Adaptor(const String& string, UTF8ConversionMode mode = kLenientUTF8Conversion); ~StringUTF8Adaptor();
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index dc2a98d9..7c4e8ab 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -487,7 +487,6 @@ crbug.com/881057 [ Mac ] external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-paint-clip-005.html [ Failure ] crbug.com/880802 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-paint-ignored-cases-ruby-stacking-and-clipping-001.html [ Failure ] crbug.com/881057 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-paint-stacking-context-001b.html [ Failure ] -crbug.com/863454 external/wpt/css/vendor-imports/mozilla/mozilla-central-reftests/contain/contain-size-multicol-003.html [ Failure ] # [css-align]
diff --git a/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/iframe.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/iframe.tentative.https.sub.html index 461d9f2..b916e3a 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/iframe.tentative.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/iframe.tentative.https.sub.html
@@ -65,21 +65,21 @@ create_test("{{host}}:{{ports[https][0]}}", USER, { "dest": "nested-document", "site": "same-origin", - "user": "?T", + "user": "?1", "mode": "nested-navigate" }); create_test("{{hosts[][www]}}:{{ports[https][0]}}", USER, { "dest": "nested-document", "site": "same-site", - "user": "?T", + "user": "?1", "mode": "nested-navigate" }); create_test("{{hosts[alt][www]}}:{{ports[https][0]}}", USER, { "dest": "nested-document", "site": "cross-site", - "user": "?T", + "user": "?1", "mode": "nested-navigate" }); </script>
diff --git a/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/window-open.tentative.https.sub.html b/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/window-open.tentative.https.sub.html index 0be9f2c..df13d55c 100644 --- a/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/window-open.tentative.https.sub.html +++ b/third_party/blink/web_tests/external/wpt/fetch/sec-metadata/window-open.tentative.https.sub.html
@@ -143,7 +143,7 @@ assert_header_equals(e.data, { "dest": "document", "site": "same-origin", - "user": "?T", + "user": "?1", "mode": "navigate", }); t.done(); @@ -165,7 +165,7 @@ assert_header_equals(e.data, { "dest": "document", "site": "same-site", - "user": "?T", + "user": "?1", "mode": "navigate", }); t.done(); @@ -187,7 +187,7 @@ assert_header_equals(e.data, { "dest": "document", "site": "cross-site", - "user": "?T", + "user": "?1", "mode": "navigate", }); t.done();
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/cssom-constructed-expected.txt b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/cssom-constructed-expected.txt new file mode 100644 index 0000000..443ff82 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/cssom-constructed-expected.txt
@@ -0,0 +1,19 @@ +Tests that constructed stylesheets appear properly. + +[expanded] +element.style { () + +[expanded] +div { () + color: red; + +[expanded] +div { (user agent stylesheet) + display: block; + +======== Inherited from html ======== +[expanded] +html { (user agent stylesheet) +/-- overloaded --/ color: -internal-root-color; + +
diff --git a/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/cssom-constructed.js b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/cssom-constructed.js new file mode 100644 index 0000000..57d0084 --- /dev/null +++ b/third_party/blink/web_tests/http/tests/devtools/elements/styles-4/cssom-constructed.js
@@ -0,0 +1,24 @@ +// Copyright 2019 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +(async function() { + TestRunner.addResult(`Tests that constructed stylesheets appear properly.\n`); + await TestRunner.loadModule('elements_test_runner'); + await TestRunner.showPanel('elements'); + await TestRunner.loadHTML(` + <div id="inspected">Text</div> + `); + await TestRunner.evaluateInPagePromise(` + const s = new CSSStyleSheet(); + s.replaceSync('div {color: red}'); + document.adoptedStyleSheets = [s]; + `); + + ElementsTestRunner.selectNodeAndWaitForStyles('inspected', dump); + + function dump() { + ElementsTestRunner.dumpSelectedElementStyles(true); + TestRunner.completeTest(); + } +})();
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index dccb1ff..5badbd820 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -13886,10 +13886,11 @@ </histogram> <histogram name="Bookmarks.Count.OnProfileLoad" units="bookmarks" - expires_after="2019-03-24"> + expires_after="2019-09-24"> <owner>supertri@chromium.org</owner> <owner>isherman@chromium.org</owner> <owner>aidanday@google.com</owner> + <owner>mamir@chromium.org</owner> <summary> The total number of bookmarks a user has saved. Recorded when a profile is opened - precisely, when bookmarks are loaded into storage from disk. The @@ -13898,6 +13899,40 @@ </summary> </histogram> +<histogram name="Bookmarks.Count.OnProfileLoad.DuplicateUrl" units="bookmarks" + expires_after="2019-09-24"> + <owner>mamir@chromium.org</owner> + <owner>mastiz@chromium.org</owner> + <summary> + The number of bookmarks a user has saved with a URL that is also present in + at least one other bookmark. This excludes folders (which don't have a URL). + Recorded when bookmarks are loaded into storage from disk if there is at + least one duplicate. + </summary> +</histogram> + +<histogram name="Bookmarks.Count.OnProfileLoad.EmptyTitle" units="bookmarks" + expires_after="2019-09-24"> + <owner>mamir@chromium.org</owner> + <owner>mastiz@chromium.org</owner> + <summary> + The number of bookmarks a user has saved with an empty title (strictly + speaking, i.e. does not count whitespace-only titles), including folders and + excluding the root. Recorded when bookmarks are loaded into storage from + disk if there is at least one node with an empty title. + </summary> +</histogram> + +<histogram name="Bookmarks.DuplicateAndEmptyTitleDetectionTime" units="ms" + expires_after="2019-09-24"> + <owner>mamir@chromium.org</owner> + <owner>mastiz@chromium.org</owner> + <summary> + Time to compute values to be logged for UMA metrics + Bookmarks.Count.OnProfileLoad.*. + </summary> +</histogram> + <histogram name="Bookmarks.EntryPoint" enum="BookmarksEntryPoint"> <owner>ianwen@chromium.org</owner> <summary>How users add a new bookmark.</summary>
diff --git a/ui/compositor/paint_cache.cc b/ui/compositor/paint_cache.cc index 71b2a0e..eec101fb 100644 --- a/ui/compositor/paint_cache.cc +++ b/ui/compositor/paint_cache.cc
@@ -15,8 +15,10 @@ bool PaintCache::UseCache(const PaintContext& context, const gfx::Size& size_in_context) { - if (!paint_op_buffer_) + if (!paint_op_buffer_ || + context.device_scale_factor() != device_scale_factor_) { return false; + } DCHECK(context.list_); context.list_->StartPaint(); context.list_->push<cc::DrawRecordOp>(paint_op_buffer_); @@ -25,8 +27,10 @@ return true; } -void PaintCache::SetPaintOpBuffer(sk_sp<cc::PaintOpBuffer> paint_op_buffer) { +void PaintCache::SetPaintOpBuffer(sk_sp<cc::PaintOpBuffer> paint_op_buffer, + float device_scale_factor) { paint_op_buffer_ = std::move(paint_op_buffer); + device_scale_factor_ = device_scale_factor; } } // namespace ui
diff --git a/ui/compositor/paint_cache.h b/ui/compositor/paint_cache.h index 04ae875..1863e202 100644 --- a/ui/compositor/paint_cache.h +++ b/ui/compositor/paint_cache.h
@@ -36,12 +36,19 @@ // Only PaintRecorder can modify these. friend PaintRecorder; - void SetPaintOpBuffer(sk_sp<cc::PaintOpBuffer> paint_op_buffer); + void SetPaintOpBuffer(sk_sp<cc::PaintOpBuffer> paint_op_buffer, + float device_scale_factor); // Stored in an sk_sp because PaintOpBuffer requires this to append the cached // items into it. sk_sp<cc::PaintOpBuffer> paint_op_buffer_; + // This allows paint cache to be device scale factor aware. If a request for + // a cache entry is made that does not match the stored cache entry's DSF, + // then we can reject it instead of returning the incorrect cache entry. + // See https://crbug.com/834114 for details. + float device_scale_factor_ = 0.f; + DISALLOW_COPY_AND_ASSIGN(PaintCache); };
diff --git a/ui/compositor/paint_recorder.cc b/ui/compositor/paint_recorder.cc index f85d3cb..173c88bc 100644 --- a/ui/compositor/paint_recorder.cc +++ b/ui/compositor/paint_recorder.cc
@@ -74,7 +74,8 @@ if (cache_) { local_list_->EndPaintOfUnpaired(gfx::Rect()); local_list_->Finalize(); - cache_->SetPaintOpBuffer(local_list_->ReleaseAsRecord()); + cache_->SetPaintOpBuffer(local_list_->ReleaseAsRecord(), + context_.device_scale_factor()); cache_->UseCache(context_, recording_size_); } else { gfx::Rect bounds_in_layer = context_.ToLayerSpaceBounds(recording_size_);
diff --git a/ui/display/manager/display_manager.cc b/ui/display/manager/display_manager.cc index 03816a0..11eee291 100644 --- a/ui/display/manager/display_manager.cc +++ b/ui/display/manager/display_manager.cc
@@ -1343,7 +1343,6 @@ return true; } } - return false; } // Mirror mode should remain unchanged as long as there are more than one // connected displays. @@ -2231,6 +2230,13 @@ if (num_connected_displays_ <= 1) return; + // The display prefs have just been loaded and we're waiting for the + // reconfiguration of the displays to apply the newly loaded prefs. We should + // not overwrite the newly-loaded external display mirror configs. + // https://crbug.com/936884. + if (should_restore_mirror_mode_from_display_prefs_) + return; + // External displays mirrored because of forced tablet mode mirroring should // not be considered candidates for restoring their mirrored state. // https://crbug.com/919994.
diff --git a/ui/login/BUILD.gn b/ui/login/BUILD.gn new file mode 100644 index 0000000..3d66b87 --- /dev/null +++ b/ui/login/BUILD.gn
@@ -0,0 +1,8 @@ +# Copyright 2019 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//third_party/closure_compiler/compile_js.gni") + +js_library("display_manager_types") { +}
diff --git a/ui/login/display_manager_types.js b/ui/login/display_manager_types.js index c50024e..389ead2 100644 --- a/ui/login/display_manager_types.js +++ b/ui/login/display_manager_types.js
@@ -7,6 +7,18 @@ * Closure compiler type definitions used by display_manager.js . */ +/** + * @typedef {{ + * commonScreenSize: (boolean|undefined), + * enableDebuggingAllowed: (boolean|undefined), + * enterDemoModeAllowed: (boolean|undefined), + * noAnimatedTransition: (boolean|undefined), + * postponeEnrollmentAllowed: (boolean|undefined), + * resetAllowed: (boolean|undefined), + * startEnrollmentAllowed: (boolean|undefined), + * toggleKioskAllowed: (boolean|undefined), + * }} + */ var DisplayManagerScreenAttributes = {}; /**
diff --git a/ui/shell_dialogs/select_file_dialog_mac.mm b/ui/shell_dialogs/select_file_dialog_mac.mm index 21c7e89..0d8913e 100644 --- a/ui/shell_dialogs/select_file_dialog_mac.mm +++ b/ui/shell_dialogs/select_file_dialog_mac.mm
@@ -268,10 +268,10 @@ // this by never hiding extensions in that case. base::FilePath::StringType penultimate_extension = default_path.RemoveFinalExtension().FinalExtension(); - if (!penultimate_extension.empty() && - penultimate_extension.length() <= 5U) { + if (!penultimate_extension.empty()) { [dialog setExtensionHidden:NO]; } else { + [dialog setExtensionHidden:YES]; [dialog setCanSelectHiddenExtension:YES]; } } else {
diff --git a/ui/shell_dialogs/select_file_dialog_mac_unittest.mm b/ui/shell_dialogs/select_file_dialog_mac_unittest.mm index 4f71b81..8249888f 100644 --- a/ui/shell_dialogs/select_file_dialog_mac_unittest.mm +++ b/ui/shell_dialogs/select_file_dialog_mac_unittest.mm
@@ -463,12 +463,14 @@ TEST_F(SelectFileDialogMacTest, MultipleExtension) { const std::string fake_path_normal = "/fake_directory/filename.tar"; const std::string fake_path_multiple = "/fake_directory/filename.tar.gz"; + const std::string fake_path_long = "/fake_directory/example.com-123.json"; FileDialogArguments args(GetDefaultArguments()); args.default_path = base::FilePath(FILE_PATH_LITERAL(fake_path_normal)); SelectFileWithParams(args); NSSavePanel* panel = GetPanel(); EXPECT_TRUE([panel canSelectHiddenExtension]); + EXPECT_TRUE([panel isExtensionHidden]); ResetDialog(); args.default_path = base::FilePath(FILE_PATH_LITERAL(fake_path_multiple)); @@ -476,6 +478,13 @@ panel = GetPanel(); EXPECT_FALSE([panel canSelectHiddenExtension]); EXPECT_FALSE([panel isExtensionHidden]); + + ResetDialog(); + args.default_path = base::FilePath(FILE_PATH_LITERAL(fake_path_long)); + SelectFileWithParams(args); + panel = GetPanel(); + EXPECT_FALSE([panel canSelectHiddenExtension]); + EXPECT_FALSE([panel isExtensionHidden]); } // Test to ensure lifetime is sound if a reference to the panel outlives the